﻿# -*- coding: utf-8 -*-
#
# PyExPsiN: pyexpsin.py
#
# Copyright (C) 2007-2011 Sergio Damián Vernis
# Author: Sergio Damián Vernis
# URL: http://sourceforge.net/projects/pyexpsin/
#
# Distributed under the terms of the GNU General Public License
# (GPL). See the license.txt that came with this file.

"""
Este modulo inicializa todo, muestra los estimulos, toma los tiempos, etc.
This module starts everything, show stimulus, take times, etc.
"""

# Debug
import os
import sys
import time
import string
import ConfigParser

# Change to Application Directory
AppDir = string.join(sys.argv[0].split(os.sep)[0:-1],os.sep)
if AppDir:
	os.chdir(AppDir)

# Portable Config
AppName = sys.argv[0].split(os.sep)[-1].split('.')[0]
global PortableResults, PortableLog, PortableINI
PortableResults = ''
PortableLog     = ''
PortableINI     = ''
PortableConfig  = 'portable.ini'
if os.access(PortableConfig,os.F_OK ):
	config = ConfigParser.ConfigParser()
	seccion = 'Portable'
	config.readfp(open(PortableConfig,'r'))
	RootDir = string.join(os.getcwd().split(os.sep)[0:-1],os.sep)
	UseLabDir = 0
	try:
		UseLabDir = config.get(seccion,"UseLabDir").strip()
	except:
		pass
	LabDir = ''
	try:
		LabDir = config.get(seccion,"LabDir").strip().replace('\\',os.sep).replace('/',os.sep)
	except:
		pass
	if LabDir:
		RootDir = os.getcwd() + os.sep + LabDir + os.sep + AppName
	elif UseLabDir:
		RootDir = os.getcwd() + os.sep + AppName
	PortableResults = RootDir + os.sep + config.get(seccion,"Results").strip().replace('\\',os.sep).replace('/',os.sep)
	PortableLog     = RootDir + os.sep + config.get(seccion,"Log").strip().replace('\\',os.sep).replace('/',os.sep)
	# Pyexpsin.ini is optional
	PortableINI     = os.getcwd()
	try:
		PortableINI = RootDir + os.sep + config.get(seccion,"Ini").strip().replace('\\',os.sep).replace('/',os.sep)
	except:
		pass
	# Create PortableLog directory if necesary
	if not os.path.exists(PortableLog):
		os.makedirs(PortableLog)
	# Create PortableINI directory if necesary
	if not os.path.exists(PortableINI):
		os.makedirs(PortableINI)

# Debug Log
global debugging, DebugWarning ; debugging = 1 ; DebugWarning = 1
global LogTarget
if PortableResults and PortableLog and PortableINI:
	LogTarget = PortableLog + os.sep + 'pyexpsin.log'
else:
	LogTarget = os.path.expanduser("~")
	if LogTarget=="~":
		LogTarget = os.getcwd()[0:2]
	LogTarget = LogTarget + os.sep + 'pyexpsin.log'

def debug(Message):
	if debugging:
		Msg = Message.encode('utf-8','ignore')
		print(Msg)
		file(LogTarget,'a').write(Msg+'\n')

print(u'Ventana de seguimiento de mensajes y errores.')
print(u'No cierre esta ventana, o terminará el experimento abruptamente.')
debug('*** Start Debug: '+time.strftime('%x %X UTC', time.gmtime(time.time())))
# End Debug

# Build
BuildFile = 'build.txt'
global buildnumber
buildnumber = 0
if os.access(BuildFile,os.F_OK):
	buildnumber = open(BuildFile,'r').read().splitlines()[0]
	debug('*** Build: '+str(buildnumber))
# End - Build

debug(u'+++ Imports')
import getopt
import random
import re
import ooolib
import csv
import codecs
import cStringIO
import hashlib
import copy
import fpformat
import subprocess
import uuid
import decimal
import math
import platform
import pygame
from pygame.locals import *
# JIT compiler load, if not loaded, you can't use JIT.
global psycoLoaded ; psycoLoaded = 1
try:
	import psyco
except ImportError:
	debug("Fallo al intentar importar: psyco")
	psycoLoaded = 0
# GUI wx Module control, if not loaded, you can't use GUI interface.
global wxLoaded ; wxLoaded = 1
try:
	import wx
except ImportError:
	debug("Fallo al intentar importar: wx")
	wxLoaded = 0
# serial Module control, if not loaded, you can't use EEG sync.
global SerialLoaded ; SerialLoaded = 1
try:
	import serial
except ImportError:
	debug("Fallo al intentar importar: serial")
	SerialLoaded = 0
if sys.platform[0:3]=="win":
	# Windows API Module control, if not loaded, we use some workarrounds.
	global win32comLoaded ; win32comLoaded = 1
	global win32apiLoaded ; win32apiLoaded = 1
	global win32TerminateProcessLoaded ; win32TerminateProcessLoaded = 1
	try:
		from win32com.shell import shell
	except ImportError:
		debug("Fallo al intentar importar: win32com.shell")
		win32comLoaded = 0
	try:
		from win32api import GetSystemMetrics
	except ImportError:
		debug("Fallo al intentar importar: win32api")
		win32apiLoaded = 0
	try:
		# Kill the process using pywin32
		from win32api import GenerateConsoleCtrlEvent
		from win32con import CTRL_BREAK_EVENT
		from win32process import CREATE_NEW_PROCESS_GROUP
	except ImportError:
		debug("Fallo al intentar importar: win32api.GenerateConsoleCtrlEvent")
		win32TerminateProcessLoaded = 0

def init(tasks=[],groups=[],conditions=[],excludeablelist=[],forcegui=1,forceXgui=0,firstisdefault=0,
		 Events=[KEYDOWN], modes = FULLSCREEN | HWSURFACE | HWPALETTE | DOUBLEBUF):
	"""Starts all.  You must run this at first.
	You must give task and groups, even if you have only one.
	
	Parameters:
	Tasks: are the experiments in your script file.
	Groups: are your experimentals groups.
	forcegui      : 1 force graphical interface
	forceXgui     : 1 force extended interfase
	firstisdefault: 1 first value in group and tasks as taked as default.
	Events: List of not Bloqued Events. (Default Keyboard)"""
	global debugging, GoDownBad
	GoDownBad = 0
	debug('init')
	if psycoLoaded:
		psyco.full()
	pygame.quit() #clean out anything running
	pygame.init()
	random.seed()
	global Tasks,Groups,Conditions,prueba,grupo,Condition,screen, clock
	global configflag, expertflag, ExcludeableList
	Tasks = tasks
	Groups = groups
	Conditions = conditions
	ExcludeableList = excludeablelist
	clock = pygame.time.Clock()
	initvariables()
	diskconfig('read')
	if firstisdefault:
		if Tasks:
			prueba = Tasks[0]
		if Groups:
			grupo = Groups[0]
		if Conditions:
			Condition = Conditions[0]
	tomarparametros()
	# If exists Groups and Tasks, but they aren't specified, then Expert Config Windows will be showed.
	if  (((not grupo and Groups) or (not prueba and Tasks) or (not Condition and Conditions))
	or (grupo and not (grupo in Groups)) or (prueba and not (prueba in Tasks))
	or (Condition and not (Condition in Conditions))):
		configflag = expertflag = 1
	if forcegui:
		configflag = 1
	if forceXgui:
		configflag = expertflag = 1
	if wxLoaded and configflag:
		configure()
	if usersize in pygame.display.list_modes():
		profundidad=pygame.display.mode_ok(usersize,modes,32)
		if profundidad:
			screen = pygame.display.set_mode(usersize,modes,profundidad)
		else:
			debugging = 1
			debug('*** Error: Init: Error en profundidad de colores.')
			sys.exit()
	else:
		debugging = 1
		debug('*** Error: La resolucion de pantalla de '+str(usersize)[1:-1].replace(', ','x')+' no esta disponible.')
		debug('Los modos disponibles son: '+str(pygame.display.list_modes()))
		sys.exit()
	## Mouse
	pygame.mouse.set_cursor(*thickarrowwhite_cursor)
	pygame.mouse.set_visible(False) # Esconder el cursor del ratón
	# Eventos
	global EVENTS, NOEVENTS
	EVENTS = Events
	# Keydown event must be every time.
	if not KEYDOWN in EVENTS:
		EVENTS.append(KEYDOWN)
	NOEVENTS = copy.copy(ALL_EVENTS)
	for Evento in EVENTS:
		NOEVENTS.remove(Evento)
	pygame.event.set_blocked(NOEVENTS)
	## pygame.event.set_grab = True
	cleanscreen()

def ShowMouse(Show=None):
	if not (Show is None):
		pygame.mouse.set_visible(Show)

def initvariables():
	"""Setups global variables.  Don't use it, at less you now you are doing."""
	debug('initvariables')
	# constants
	global ALL_EVENTS
	ALL_EVENTS =[KEYDOWN,KEYUP,MOUSEMOTION,MOUSEBUTTONUP,MOUSEBUTTONDOWN,
		JOYAXISMOTION,JOYBALLMOTION,JOYHATMOTION,JOYBUTTONUP,JOYBUTTONDOWN]
	global STIMULUSTYPEIMAGE, STIMULUSTYPEVIDEO, STIMULUSTYPESOUND, STIMULUSTYPESPRIT, STIMULUSTYPEACTIO
	STIMULUSTYPEIMAGE = 0
	STIMULUSTYPEVIDEO = 1
	STIMULUSTYPESOUND = 2
	STIMULUSTYPESPRIT = 3
	STIMULUSTYPEACTIO = 4
	# sprits
	global NextSpritUpdate
	NextSpritUpdate = 0
	global ShowVideo,background,textcolor,letra,SoundRequired
	global black,white,grey,red,green,blue,yellow
	global StartTime, SistemaOperativo
	StartTime = time.time()
	SoundRequired = 0
	ShowVideo = 1
	black = 0, 0, 0
	white = 255, 255, 255
	grey = 180, 180, 180
	red = 255, 0, 0
	green = 0, 255, 0
	blue = 0, 0, 255
	yellow = 255, 255, 0
	background = black
	textcolor = white
	letra='Fonts'+os.sep+"freesansbold.ttf"
	global UUID, UCID, RESEARCHER
	global codigosujeto, generosujeto, edadsujeto, EdadesValidas
	UUID = str(uuid.uuid4())
	RESEARCHER = ''
	codigosujeto = ''
	generosujeto = ''
	edadsujeto = ''
	EdadesValidas = str(range(131)).replace(",","").replace("[","").replace("]","").split()
	global Condition, prueba, grupo
	Condition = ''
	prueba = ''
	grupo = ''
	global home,usersize,directorio,configfile
	global eegsync,eegsyncport,eegbaudrate,eegsyncmintime
	for tamanio in pygame.display.list_modes():
		size = width, height = tamanio
		if width>height:
			usersize = size
			break
	if PortableResults and PortableLog and PortableINI:
		# Portable Configuration
		home       = PortableLog
		configfile = PortableINI + os.sep + 'pyexpsin.ini'
		documentos = PortableResults
		directorio = PortableResults
	else:
		# Normal Configuration
		home=os.path.expanduser("~")
		if sys.platform[0:3]=="win":
			if win32apiLoaded:
				width = GetSystemMetrics (0)
				height = GetSystemMetrics (1)
				usersize = width, height
			if home=="~":
				home=os.getcwd()[0:2]
			if win32comLoaded:
				df = shell.SHGetDesktopFolder()
				pidl = df.ParseDisplayName(0, None,"::{450d8fba-ad25-11d0-98a8-0800361b1103}")[1]
				documentos = shell.SHGetPathFromIDList(pidl)
			else:
				MisDocumentos=['Mis documentos','My documents','Meus documentos',
				'Meine dokumente','Miei documenti','Mes documents','Mijn documenten',
				'Documentos','Documents','Dokumente','Documenti','Documenten']
				for traduccion in MisDocumentos:
					probar=home+os.sep+traduccion
					if os.path.exists(probar):
						documentos=probar
						break
			configfile = home + os.sep + 'pyexpsin.ini'
		else:
			documentos = home
			configfile = home + os.sep + '.pyexpsin.ini'
		directorio=documentos+os.sep+'Mis resultados del experimento'
	# Sistema Operativo
	if sys.platform[0:3]=="win":
		wv = ['Win32s on Windows 3.1','Windows 95/98/ME','Windows NT/2000/XP','Windows CE']
		WV = sys.getwindowsversion()
		if (len(wv)-1)>=WV[3]:
			system = wv[WV[3]]
		else:
			system = str(WV[3])
		SistemaOperativo = str(sys.platform + ': ' + system + ': ' + str(WV[0]) + '.' + str(WV[1]) + ': ' + str(WV[2]))
		UserDomain = str(os.getenv('USERDOMAIN'))
		ComputerName = str(os.getenv('COMPUTERNAME'))
		LogonServer = str(os.getenv('LOGONSERVER'))
		Processor_Identifier = str(os.getenv('PROCESSOR_IDENTIFIER'))
		## print 'SistemaOperativo: ', SistemaOperativo
		## print 'UserDomain: ', UserDomain
		## print 'ComputerName: ', ComputerName
		## print 'LogonServer: ', LogonServer
		## print 'Processor_Identifier: ', Processor_Identifier
		Computer = SistemaOperativo + UserDomain + ComputerName + LogonServer + Processor_Identifier
	else:
		SistemaOperativo = str(sys.platform)
		PNode = str(platform.node())
		PPlatform = str(platform.platform())
		PRelease = str(platform.release())
		PDist = str(platform.dist())
		PMachine = str(platform.machine())
		## print 'SistemaOperativo: ', SistemaOperativo
		## print 'PNode:            ', PNode
		## print 'PPlatform:        ', PPlatform
		## print 'PRelease:         ', PRelease
		## print 'PDist:            ', PDist
		## print 'PMachine:         ', PMachine
		Computer = SistemaOperativo + PNode + PPlatform + PRelease + PDist + PMachine
	UCID = str(hashlib.sha1(Computer).hexdigest())
	if not os.path.exists(directorio):
		os.makedirs(directorio)
	eegsync = 0
	eegsyncport = 0
	eegbaudrate = 115200 # <- maximo. Estandar lento es 9600
	eegsyncmintime = 10
	global SoundRecorder
	SoundRecorder = 0
	global thickarrowwhite_strings, thickarrowwhite_cursor
	thickarrowwhite_strings = ( #sized 16.16
		"        .       ",
		"       ...      ",
		"       ...      ",
		"      ..X..     ",
		"      ..X..     ",
		"     ..XXX..    ",
		"     ..XXX..    ",
		"    ..XXXXX..   ",
		"    ..XXXXX..   ",
		"   ..XXXXXXX..  ",
		"   ..XXXXXXX..  ",
		"  ..XXXXXXXXX.. ",
		"  .....XXX..... ",
		"      ..X..     ",
		"      ..X..     ",
		"      .....     ")
	cursordata, cursormask = pygame.cursors.compile(thickarrowwhite_strings, ".", "X")
	thickarrowwhite_cursor = ((16,16),(8,1),cursordata,cursormask)
	global ControlHeaders
	ControlHeaders = ['OK:', 'ID:', 'RS:', 'TI:', 'TF:', 'US:', 'OS:', 'FS:',
					  'DS:', 'ES:', 'DM:', 'BD:', 'SC:', 'XL:', 'BB:', 'SR:',
					  'QR:', 'RR:', 'SF:','CD:']

	
def definefilenames():
	"""Define File Names. Don't use it, at less you now you are doing."""
	# Nombres de Archivos
	global NombreArchivoDatosTSV, NombreArchivoDatosODS, NombreArchivoSonido
	global TipoDeArchivoSonido, SoundFileName
	global soundrecorderpid, soundrecordernumberfile, SoundRecordFolder
	soundrecorderpid = 0
	soundrecordernumberfile = 1
	TipoDeArchivoDatosTSV=".tsv"
	TipoDeArchivoDatosODS=".ods"
	TipoDeArchivoSonido=".wav"
	SoundFileName=""
	NombreBaseArchivo=codigosujeto+"_"+generosujeto+edadsujeto
	if Condition:
		NombreBaseArchivo="C"+Condition+"-"+NombreBaseArchivo
	if grupo:
		NombreBaseArchivo="G"+grupo+"-"+NombreBaseArchivo
	if prueba:
		NombreBaseArchivo=prueba+"-"+NombreBaseArchivo
	NombreArchivoDatosTSV=NombreBaseArchivo+TipoDeArchivoDatosTSV
	NombreArchivoDatosODS=NombreBaseArchivo+TipoDeArchivoDatosODS
	NombreArchivoSonido=NombreBaseArchivo
	contador=0
	while (os.access(directorio+os.sep+NombreArchivoDatosTSV,os.F_OK)
		or os.access(directorio+os.sep+NombreArchivoDatosODS,os.F_OK)):
		NombreArchivoDatosTSV=NombreBaseArchivo+"-"+str(contador)+TipoDeArchivoDatosTSV
		NombreArchivoDatosODS=NombreBaseArchivo+"-"+str(contador)+TipoDeArchivoDatosODS
		NombreArchivoSonido=NombreBaseArchivo+"-"+str(contador)
		contador+=1
	SoundRecordFolder = directorio+os.sep+NombreArchivoSonido

def IsSoundRequired(Value=None):
	"""Sets or Return SoundRequired status.  Default value is None.
	
	Parameters:
	Value: New Value, must be a Python True/False value, as 0/1.
	
	Returns: If Value is given, no returns.
	         If Value isn't given, returns actual value.
	"""
	debug('IsSoundRequired')
	global SoundRequired
	if Value is None:
		return SoundRequired
	else:
		SoundRequired = int(Value)

def diskconfig(action):
	"""Reads and Writes config file.
	You can use this function to force this action.
	
	Parameters:
	action: 'write' / 'read'
	
	Config file is saved in:
	Linux/Unix/Mac: /home/user/ as .pyexpsin.ini
	Windows: \Documents and setings\user\ as pyexpsin.ini"""
	debug('diskconfig')
	global RESEARCHER,UUID,usersize,eegsync,eegsyncport,eegbaudrate,eegsyncmintime
	seccion="defaults"
	config = ConfigParser.ConfigParser()
	if action=="read" and os.access(configfile,os.F_OK ):
		config.readfp(open(configfile,'r'))
		try:
			RESEARCHER=config.get(seccion,"RESEARCHER")
		except:
			pass
		try:
			eegsync=int(config.getboolean(seccion,"eegsync"))
		except:
			pass
		try:
			eegsyncport=config.getint(seccion,"eegsyncport")
		except:
			pass
		try:
			eegbaudrate=config.getint(seccion,"eegbaudrate")
		except:
			pass
		try:
			eegsyncmintime=config.getint(seccion,"eegsyncmintime")
		except:
			pass
		try:
			resolucion=config.get(seccion,"usersize")[1:-1].lower().split(', ')
		except:
			pass
		try:
			usersize = width, height =  int(resolucion[0]),int(resolucion[1])
		except:
			pass
		try:
			UUID = config.get(seccion,"UUID")
		except:
			diskconfig('write')
	elif action=="read" and not os.access(configfile,os.F_OK ):
		diskconfig('write')
	elif action=="write":
		config.add_section(seccion)
		config.set(seccion,"RESEARCHER",RESEARCHER)
		config.set(seccion,"UUID",UUID)
		config.set(seccion,"eegsync",eegsync)
		config.set(seccion,"eegsyncport",eegsyncport)
		config.set(seccion,"eegbaudrate",eegbaudrate)
		config.set(seccion,"eegsyncmintime",eegsyncmintime)
		config.set(seccion,"usersize",usersize)
		config.write(open(configfile,'w'))


class avisos:
	"""Esta clase contiene los avisos de alerta
	This class content alert warnings"""
	def __init__(self):	
		self.texto  = ""
		self.imagen = ""
		self.sonido = ""
		self.tiempo = 0
		self.retraso = 0


class aciertos(avisos):
	"""Esta clase contiene los avisos de acierto
	This class content successful warnings"""
	pass


class errores(avisos):
	"""Esta clase contiene los avisos de error
	This class content error warnings"""
	pass

class noanswer(avisos):
	"""Esta clase contiene los avisos de error
	This class content error warnings"""
	pass

class intento:
	u"""Esta clase contiene todos los datos para hacer una presentación de estímulo
	This class have all data to make an stimulus presentation"""
	def __init__(self):
		"""Inicia las propiedades de la clase
		Setups class properties"""
		self.aviso = avisos
		self.aviso.tiempo = 0
		self.aviso.retraso = 0
		self.aviso.espera = 50
		self.aviso.texto = self.cargartexto("+",10)
		self.aviso.imagen = ""
		self.aviso.sonido = 0
		self.espera = 1000
		self.haymuestra = 0
		self.hayrelacion = 0
		self.tiempomuestra = 0   # Duración de la presentación del estimulo de muestra
		self.GlobalPresentarMuestraMaxSSST = 0
		self.retraso = 0         # De los estimulos a emparejar con la muestra
		self.retrasoList = []
		self.retrasoRandom = 0
		self.HideMuestra = 0
		self.sinpersistencia = 0 # De la muestra
		self.clasesfacil = {}    # Relaciones entre los estimulos de muestra y ejemplo, fácil
		self.ClasesAllowExtendedClass = 0
		self.tiempolimite = 0    # Tiempo máximo para dar una respuesta
		self.feedback = 1        # Devuelve el resultado: 1 si, 0 no
		self.bien = aciertos     # A mostrar en caso de acierto
		self.bien.texto = self.cargartexto("Acierto",8)
		self.bien.tiempo = 1000
		self.bien.sonido = 0
		self.mal = errores       # A mostrar en caso de error
		self.mal.texto = self.cargartexto("Error",8)
		self.mal.tiempo = 1000
		self.mal.sonido = 0
		self.NoAnswer = noanswer # A mostrar en caso de acierto
		self.NoAnswer.texto = self.cargartexto(u"No Respondió",8)
		self.NoAnswer.tiempo = 1000
		self.NoAnswer.sonido = 0
		self.FeedBackDelay = 0
		self.FeedBackShowTime = 1000
		self.NoAnswerFeedBack = 0
		self.resultados = []
		self.numero = 0
		self.fase=""
		self.bloque=""
		self.teclas=[[K_LSHIFT],[K_RSHIFT]]
		self.keys=[K_LSHIFT,K_RSHIFT]
		self.keyalias = 0
		self.fallosonido=0
		self.checknodaldistance=0
		self.eegsync=0
		# Next 2 lines, backward compatibility
		self.LastEegSyncSignal = 0
		self.LastTakeTime = 0
		self.GlobalPresentarLastEegSyncSignal = 1
		self.GlobalPresentarLastTakeTime = 1
		self.StimulusTakeTimeMaxCount = 0
		self.StimulusNumber=0
		self.Result=1
		self.IncrementNumero = 1
		# Presentar
		self.GlobalPresentarMuestraTakeTime = 0
		self.GlobalPresentarMuestraEegSyncSignal = 0
		self.GlobalPresentarRelacionTakeTime = 0
		self.GlobalPresentarRelacionEegSyncSignal = 0
		self.GlobalPresentarEmparejarTakeTime = 0
		self.GlobalPresentarEmparejarEegSyncSignal = 0
		self.GlobalPresentarEmparejarTakeTimeOnlyOne = 1
		self.GlobalPresentarEmparejarEegSyncSignalOnlyOne = 1
		self.GlobalPresentarEmparejarTakeTimeOK = 0
		self.GlobalPresentarEmparejarEegSyncSignalOK = 0
		self.PresentarGetStimulusChain = 0
		# Emparejar
		self.tiempoemparejar = 0
		self.GlobalPresentarEmparejarMaxSSST = 0
		self.sinpersistenciaemparejar = 0
		self.retrasoemparejar = 0
		self.retrasoemparejarList = []
		self.retrasoemparejarRandom = 0
		self.IncludePresentarRetrasoMuestra = 0
		# Relacion
		self.tiemporelacion = 0
		self.sinpersistenciarelacion = 0
		self.retrasorelacion = 0
		self.retrasorelacionList = []
		self.retrasorelacionRandom = 0
		self.IncludePresentarRetrasoRelacion = 0
		self.HideRelacion = 0
		self.GlobalPresentarJumpPosicionEstimulo = 0
		self.GlobalLoadStimulusAddCentralPosition = 0
		# Load Stimulos (cargarestimulo)
		self.GlobalLoadStimulusText = 0
		self.GlobalLoadStimulusDivisor = 0
		self.GlobalLoadStimulusRelations = 0
		self.GlobalLoadStimulusFolder=u'Estimulos'
		self.GlobalLoadStimulusSound = 0
		self.GlobalLoadStimulusSoundExtraTime = 0
		self.GlobalLoadStimulusSoundFolder = u'Sounds'
		self.GlobalLoadStimulusSoundFileType = u'.ogg'
		# Generar
		self.GenerarGenerateNoValidChoice = 0
		self.GenerarGenerateMultipleValidChoices = 0
		# Phrases
		self.PhraseMessageNoAnswer = u'No respondió'
		self.PhraseMessageError = u'Error'
		self.PhraseMessageGood = u'Acierto'
		self.PhraseMessageRight = u'La frase es correcta'
		self.PhraseMessageWrong = u'Esta es la frase correcta'
		self.PhraseErrorType = 0
		self.PhraseVerboseFeedBack = 0
		self.GlobalPharseTimeBetweenWords = 250
		self.GlobalPharseDelayAfterLastSound = 0
		self.GlobalPharseWordByWord = 0
		self.GlobalPharseCleanLastWordByWord = 0
		self.GlobalPharseTimeBetweenWordByWord = 0
		self.SavePhraseErrorTypeAsResult = 0
		self.SavePhraseExtraDataKeyAsResult = ''
		# Response
		self.TakeResponseFromStart = 0
		self.ShowAllStimulus = 1
		# Sprites
		self.SpritUpdateDelay = 200
		# User Headers
		self.userheaders = []
		# Presentation
		self.CleanScreenBeforeStimulus = 1
		self.CleanScreenAfterResponse = 1
		self.EventType = [KEYDOWN]
		self.ShowExample = 1
		# nBack
		self.nBackNumber = None
		self.nBackAlwaysResponse = 0
		# Stroop
		self.AliasTarget = None
		# AGL
		self.AGLType = ''
		self.AGLPos = ''
		self.AGLTargets = []
		self.AGLExtraStimulusChain = []
		self.PresentarSaveResultsNow = 1
		self.PresentarFullResult = []
		self.IncludePresentarFullResultTime = 0
		self.AGLCertaintyTargets = []
		self.AGLCertaintyKeys = []
		self.AGLCertaintyKeysAlias = []
		self.AGLAskCertainty = 0
		self.AGLWithCertainty = 0
		self.AGLExperiment = 0
		self.AGLsep = []
		self.AGLConfirmStimulus = 0
		self.AGLConfirmStimulusDefaultOptions = 1
		self.AGLConfirmStimulusDefaultColors = 1
		self.AGLConfirmStimulusFontDivisor = 12
		self.AGLConfirmStimulusPrompt = u'¿Palabra?'
		self.AGLConfirmStimulusTimeLimit = 0
		self.TrialSep = 0
		# Feedback
		self.NoAnswerNoFeedback = 0
		# Mouse
		self.UseMouse = 0
		self.MouseButton = 0
		self.MouseSelectedKey = 0
		self.UsePresentarClic = 0
		# FullScreen
		self.FullScreenUsedAsSeparator = 0
		# Preguntar
		self.PreguntarPromptFontColor = white
		self.PreguntarInputAreaColor = white
		self.PreguntarInputTextColor = black
		self.PreguntarBackColor = black
		self.PreguntarInputBoxInputColor = blue
		self.PreguntarIgnoreReturn = 0
		self.PreguntarIgnoreBackSpace = 0
		self.PreguntarCheckValidImmediately = 0
		self.PreguntarCenterInputToValidity = 0
		self.PreguntarForceUpperCase = 0
		self.PreguntarTimeLimit = 0
		self.PreguntarTime = 0
		self.PreguntarTimeLimitReached = 0
		# Debug
		global soundrecorderpid
		soundrecorderpid = 0
		global DebugWarning
		if debugging and DebugWarning:
			DebugWarning = 0
			mensaje=LogTarget.split(os.sep)
			NombreArchivo = mensaje[-1]
			mensaje.remove(NombreArchivo)
			if len(mensaje)>1:
				mensaje[0]=mensaje[0]+os.sep+mensaje[1]
				mensaje.remove(mensaje[1])
			for i in range(len(mensaje)):
				mensaje[i]=mensaje[i]+os.sep
			mensaje.insert(0,"Seguimiento de errores guardados en:")
			mensaje.append("Con el nombre:")
			mensaje.append(NombreArchivo)
			mensaje.append("Para continuar presione")
			mensaje.append("La Barra Espaciadora")
			self.texto(mensaje)
		# Codigo Sujeto
		if not RESEARCHER:
			self.PreguntarInvestigador()
		if not codigosujeto:
			self.PreguntarCodigoSujeto()
		if not generosujeto:
			self.PreguntarGeneroSujeto()
		if not edadsujeto:
			self.PreguntarEdadSujeto()
		self.SaveAsFileFormat = 'csv'
		definefilenames()


	"""Metodos
	Methods"""
	def Preguntar(self,prompt_string,valid=[],fontdivisor=15):
		"""Ask for prompt_string
		
		Parameters:
		prompt_string: Message to show.
		valid = Valid Values.
		fontdivisor = default 15
		
		Class properties:
		self.PreguntarPromptFontColor = white
		self.PreguntarInputAreaColor = white
		self.PreguntarInputTextColor = black
		self.PreguntarBackColor = black
		self.PreguntarInputBoxInputColor = blue
		self.PreguntarIgnoreReturn = 0
		self.PreguntarIgnoreBackSpace = 0
		self.PreguntarCheckValidImmediately = 0
		self.PreguntarCenterInputToValidity = 0
		
		Returns: Input string.
		
		grabbing text input in pygame posted January 25, 2007 by eedok,
		in http://geekswhoshower.com/news/3/"""
		debug('Preguntar')
		return_string="" #the value to be returned
		font=pygame.font.Font(letra,screen.get_width()/fontdivisor)
		#calculate the size of the input box, and set it to the 
		width,height = font.size(prompt_string)
		if valid:
			Vwidth,Vheight = font.size(valid)
		else:
			Vwidth,Vheight = width,height
		y=screen.get_height()/2
		x=(screen.get_width()-width)/2
		Vx=(screen.get_width()-Vwidth)/2
		height=height*2+10
		width=width+10
		box = pygame.Rect((x-5, y-5), (width,height))
		text = font.render(prompt_string,True,self.PreguntarPromptFontColor)
		#calculate the white part of the input area
		input_area = pygame.Rect((x, y+height/2-5), (width-10,height/2-5))
		#loop until done(set if enter or escape is hit)
		done = 0
		final_return_string = ''
		antes = pygame.time.get_ticks()
		limite = antes + self.PreguntarTimeLimit
		despues = pygame.time.get_ticks()
		while (not done) and (not quickrandomresponse):
			screen.fill(self.PreguntarBackColor)
			#draw the blue box around the input	
			screen.fill((self.PreguntarInputBoxInputColor),box)
			screen.blit(text,(x,y))
			#fill the input area with white
			if self.PreguntarInputAreaColor:
				screen.fill((self.PreguntarInputAreaColor),input_area)
			#put what's currently inputted into the input area
			input_text = font.render(return_string,True,(self.PreguntarInputTextColor))
			if self.PreguntarCenterInputToValidity:
				screen.blit(input_text,(Vx,y+height/2-5))
			else:
				screen.blit(input_text,(x,y+height/2-5))
			pygame.display.flip()
			# Take an event
			event=pygame.event.poll()
			if event.type == pygame.KEYDOWN:
				#if escape was hit assume the user doesn't want to enter anything, return nothing
				if event.key == pygame.K_ESCAPE:
					self.salir()
				#if return was hit, assume the user is finished entering text and return what's been entered
				elif event.key == pygame.K_RETURN and (not self.PreguntarIgnoreReturn):
					if return_string:
						if (not valid) or (return_string in valid):
							try:
								final_return_string = string.join(re.split(' *',return_string.strip()),'_').encode()
								done = 1
							except UnicodeEncodeError:
								self.texto(["No ingrese: la ñ","NI: Letras Acentuadas (á, é, í, ó, ú, ü, etc.)", "Para continuar presione:","La Barra Espaciadora"])
						elif valid:
							self.texto(["Ingrese un valor valido.", "Para continuar presione:","La Barra Espaciadora"])
				#if backspace is hit, move the carat back one space and destroy the last letter
				elif event.key == pygame.K_BACKSPACE and (not self.PreguntarIgnoreBackSpace):
					#make sure there's something in the string first, don't want to kill what's not there
					if len(return_string)>0:
						return_string=return_string[0:len(return_string)-1]
				else:
					#add the typed letter to the string
					if self.PreguntarForceUpperCase:
						return_string=return_string+event.unicode.upper()
					else:
						return_string=return_string+event.unicode
				if self.PreguntarCheckValidImmediately and valid:
					if (valid.upper()==return_string) or (valid[0:len(return_string)].upper()!=return_string):
						final_return_string = return_string
						done = 1
			despues = pygame.time.get_ticks()
			if self.PreguntarTimeLimit and limite<=despues:
				self.PreguntarTimeLimitReached = 1
				done = 1
		self.PreguntarTime = despues - antes
		debug('final_return_string: '+final_return_string)
		cleanscreen()
		return final_return_string

	def PreguntarInvestigador(self):
		"""Ask experimental researcher name.  No Parameters.  No Returns."""
		debug('PreguntarInvestigador')
		global RESEARCHER
		RESEARCHER = self.Preguntar(u"¿Nombre del investigador?:")

	def PreguntarCodigoSujeto(self):
		"""Ask experimental subject code.  No Parameters.  No Returns."""
		debug('PreguntarCodigoSujeto')
		global codigosujeto
		codigosujeto = self.Preguntar(u"Ingrese el código del sujeto:")

	def PreguntarEdadSujeto(self):
		"""Ask experimental subject age.  No Parameters.  No Returns."""
		debug('PreguntarEdadSujeto')
		global edadsujeto
		edadsujeto = self.Preguntar(u"Ingrese la edad del sujeto (Número):",EdadesValidas,19)

	def PreguntarGeneroSujeto(self):
		"""Ask experimental subject sex.  No Parameters.  No Returns."""
		debug('PreguntarGeneroSujeto')
		global generosujeto
		generosujeto = self.Preguntar(u"Ingrese el sexo del sujeto (M/F):",["M","F"],17)
	
	def clases(self,clases,relations=0):
		"""Take N number of stimulus in N groups and make logical classes.
		Parameters:
		clases: Group of stimulos arranged in groups.
		
		Example (Equivalence):
		miintento.clases([[A1,B1,C1,D1,E1],[A2,B2,C2,D2,E2]])
		You have two classes [A1,B1,C1,D1,E1] and [A2,B2,C2,D2,E2].
		You can make more than two classes, if you want.
		
		Example (Equal, Diferent, Greater, Minor Relations)
		miintento.clases([["Stimulus"],["Relations"]],relations=1)
		miintento.clases([[I1,T1,L1,I2,T2,L2],[Eq,NE,Gt,Lt]],relations=1)
		
		In this case Stimulus and Relations must have an Python valid name.
		Valid Name must be specified by Alias parameter in
		miintento.cargarestimulo() class method.
		
		This Standard Name (Alias) must be:
		
		1. A Number: Like 1, 2, 3, 4, 5, etc.
		2. A English Alphabet Letter: Like a, A, b, B, etc.
		3. An Arismethic simbol: =, !=, >, <.
		
		Independently of the real Stimulus.
		
		Exceptions:
		= : In NombreImagen parameter is automaticaly loaded with "==" Alias.
		!=: In NombreImagen parameter is automaticaly tranformed in No Equal Math Simbol.
		
		Note: NombreImagen parameter in cargarestimulo method.
		
		This make easy know correct answers in MTS and relations experiments"""
		debug('clases: Listas de correccion')
		self.texto([u"Creando listas de corrección","Por favor, espere."],esperarevento=0)
		if not relations:
			for clase in clases:
				grupo=[]
				for elemento in clase:
					grupo.append(elemento[0])
				for referencia in grupo:
					if self.ClasesAllowExtendedClass:
						try:
							self.clasesfacil[referencia] = self.clasesfacil[referencia] + grupo
							debug('Clases: **** WARNING **** One or More Element are in more than one class.')
							## debug('Clases: Try: referencia: ' + str(referencia))
						except KeyError:
							##debug('Clases: Key Error: referencia: ' + str(referencia))
							self.clasesfacil[referencia] = grupo
					else:
						## debug('Clases: referencia: ' + str(referencia))
						self.clasesfacil[referencia] = grupo

			debug('Clases: self.clasesfacil: ' + str(self.clasesfacil))
		else:
			for muestra in clases[0]:
				for relacion in clases[1]:
					for estimulo in clases[0]:
						# Test relation between sample (muestra) and stimulus (estimulo)
						if eval(muestra[0].upper()+relacion[0]+estimulo[0].upper()):
							if self.clasesfacil.has_key(muestra[0]):
								if not (relacion[0]+estimulo[0] in self.clasesfacil[muestra[0]]):
									self.clasesfacil[muestra[0]].append(relacion[0]+estimulo[0])
							else:
								self.clasesfacil[muestra[0]] = [relacion[0]+estimulo[0]]

	def presentar(self,muestra,emparejar,relacion=[],teclaacierto=None,LugarEstimulo=None,
		IncPosicionEstimulo=1,StartPosicionEstimulo=0,SaveStimulusPosition=1,Reverse=0,
		MuestraTakeTime=None, MuestraEegSyncSignal=None,
		RelacionTakeTime=None, RelacionEegSyncSignal=None,
		EmparejarTakeTime=None, EmparejarEegSyncSignal=None,
		ExternalChains=[]):
		"""Show stimulus and waits for an answer.
		Parameters:
		muestra: Sample stimulus.
		emparejar: Match stimulus, or uniq stimulus.
		relacion: Between Sample and Stimulus.
		teclaacierto: correct key, if no self.clases used. Default: None.
		LugarEstimulo: Used internaly by NBackSpatial.  Sets the stimulus position.
		Reverse: 1 reverse presentation, first is last.  Default is 0 (False).
		
		Get back the result:  0 fail, 1 successful."""
		debug('presentar')
		estimuloelegido=''
		teclaelegida=0
		selectedkey=0
		resultado=0
		tiempo=0
		TiempoLimite=0
		posicionestimulo=3 + StartPosicionEstimulo
		posicionimagen=2
		if self.Result:
			ThisTrialFeedback = copy.copy(self.feedback)
		else:
			ThisTrialFeedback = 0
		#Stimulus Format:
		#[image, image position, shownow, solitarie show time, clear screen, delay]
		#[sound, delay]
		ASN  = 1    # Aviso Show Now
		ACS  = 1    # Aviso Clear Screen
		SSN  = 0    # Stimulus Show Now
		# Backguard compatibility - 4 lines - 2 EEG - 2 Time control
		EegSyncSignal = 0
		self.LastEegSyncSignal = self.GlobalPresentarLastEegSyncSignal
		self.LastTakeTime = self.GlobalPresentarLastTakeTime
		TakeTime = 0
		if MuestraTakeTime is None:
			MuestraTakeTime = self.GlobalPresentarMuestraTakeTime
		if MuestraEegSyncSignal is None:
			MuestraEegSyncSignal = self.GlobalPresentarMuestraEegSyncSignal
		if RelacionTakeTime is None:
			RelacionTakeTime = self.GlobalPresentarRelacionTakeTime
		if RelacionEegSyncSignal is None:
			RelacionEegSyncSignal = self.GlobalPresentarRelacionEegSyncSignal
		if EmparejarTakeTime is None:
			EmparejarTakeTime = self.GlobalPresentarEmparejarTakeTime
		if EmparejarEegSyncSignal is None:
			EmparejarEegSyncSignal = self.GlobalPresentarEmparejarEegSyncSignal
		StimulusChain=[]
		AvisoChain=[]
		if self.clasesfacil or (not (teclaacierto is None)) or (not self.Result):
			if self.aviso.tiempo and (self.aviso.texto or self.aviso.imagen or self.aviso.sonido):
				if self.aviso.sonido:
					AvisoChain.append((STIMULUSTYPESOUND, TakeTime, EegSyncSignal, self.aviso.sonido, self.aviso.retraso))
				if self.aviso.imagen:
					AvisoChain.append((STIMULUSTYPEIMAGE, TakeTime, EegSyncSignal, self.aviso.imagen[0], self.aviso.imagen[1],ASN,self.aviso.tiempo,ACS,self.aviso.espera,0))
				elif self.aviso.texto:
					AvisoChain.append((STIMULUSTYPEIMAGE, TakeTime, EegSyncSignal, self.aviso.texto[0], self.aviso.texto[1],ASN,self.aviso.tiempo,ACS,self.aviso.espera,0))
			# PS = Pre Sample
			for chain in ExternalChains:
				if 'PS' in chain:
					StimulusChain = StimulusChain + chain[0]
			# muestra == sample
			if isinstance(self.retraso,list):
				if not self.retrasoList:
					if self.retrasoRandom:
						random.shuffle(self.retraso)
					self.retrasoList = copy.copy(self.retraso)
				RetrasoMuestra = self.retrasoList.pop()
			else:
				RetrasoMuestra = self.retraso
			if muestra:
				self.haymuestra=1
			if muestra and (not self.HideMuestra):
				actual=0
				# Mouse
				istarget = 0
				for estimulo in muestra:
					if self.UseMouse and self.UsePresentarClic and (not emparejar) and (not relacion):
						if len(emparejar)<=len(self.teclas):
							istarget = self.teclas[actual][0]
						elif len(emparejar)<=len(self.keys):
							istarget = self.keys[actual]
							debug('Warning: Using indiviudal keys, not groups.')
						else:
							istarget = self.keys[actual]
							debug('Warning: More stimulus than keys.')
					imagen=estimulo[posicionimagen]
					PosicionesEstimulo=estimulo[posicionestimulo]
					if LugarEstimulo is None:
						imagenpos=PosicionesEstimulo[actual]
					else:
						imagenpos=PosicionesEstimulo[LugarEstimulo]
					SSST = copy.copy(self.tiempomuestra)
					# Sound
					StimulusSound = 0
					for eachstimuluspart in estimulo[3:]:
						if isinstance(eachstimuluspart[0],pygame.mixer.Sound):
							StimulusSound = eachstimuluspart
							SSST = copy.copy(StimulusSound[1]+self.tiempomuestra)
					if StimulusSound:
						SSST = copy.copy(StimulusSound[1]+SSST)
						if self.GlobalPresentarMuestraMaxSSST and (SSST>self.GlobalPresentarMuestraMaxSSST):
							SSST = copy.copy(self.GlobalPresentarMuestraMaxSSST)
						StimulusChain.append([STIMULUSTYPESOUND, 0, 0, StimulusSound[0], 0])
						StimulusChain.append([STIMULUSTYPEIMAGE, copy.copy(MuestraTakeTime), copy.copy(MuestraEegSyncSignal), imagen, imagenpos,SSN,copy.copy(SSST),self.sinpersistencia,RetrasoMuestra,copy.copy(istarget)])
					else:
						StimulusChain.append([STIMULUSTYPEIMAGE, copy.copy(MuestraTakeTime), copy.copy(MuestraEegSyncSignal), imagen, imagenpos,SSN,copy.copy(SSST),self.sinpersistencia,RetrasoMuestra,copy.copy(istarget)])
					actual+=1
				posicionestimulo+=IncPosicionEstimulo
			# PR = Pre Relation
			for chain in ExternalChains:
				if 'PR' in chain:
					StimulusChain = StimulusChain + chain[0]
			# relacion == relation
			if relacion:
				self.hayrelacion=1
				if isinstance(self.retrasorelacion,list):
					if not self.retrasoRelacionList:
						if self.retrasoRelacionRandom:
							random.shuffle(self.retrasoRelacion)
						self.retrasoRelacionList = copy.copy(self.retrasoRelacion)
					RetrasoRelacion = self.retrasoRelacionList.pop()
				else:
					RetrasoRelacion = self.retrasoRelacion
			if relacion and (not self.HideRelacion):
				actual=0
				for estimulo in relacion:
					imagen=estimulo[posicionimagen]
					PosicionesEstimulo=estimulo[posicionestimulo]
					imagenpos=PosicionesEstimulo[actual]
					# Sound
					StimulusSound = 0
					for eachstimuluspart in estimulo[3:]:
						if isinstance(eachstimuluspart[0],pygame.mixer.Sound):
							StimulusSound = eachstimuluspart
					if StimulusSound:
						StimulusChain.append([STIMULUSTYPESOUND, 0, 0, StimulusSound[0], 0])
						StimulusChain.append([STIMULUSTYPEIMAGE, copy.copy(RelacionTakeTime), copy.copy(RelacionEegSyncSignal), imagen, imagenpos,SSN,copy.copy(StimulusSound[1]+self.tiemporelacion),self.sinpersistenciarelacion,RetrasoRelacion,0])
					else:
						StimulusChain.append([STIMULUSTYPEIMAGE, copy.copy(RelacionTakeTime), copy.copy(RelacionEegSyncSignal), imagen, imagenpos,SSN,self.tiemporelacion,self.sinpersistenciarelacion,RetrasoRelacion,0])
					actual+=1
				posicionestimulo+=IncPosicionsEtimulo
			elif self.GlobalPresentarJumpPosicionEstimulo:
				posicionestimulo+=IncPosicionsEtimulo
			# PT = Pre Target
			for chain in ExternalChains:
				if 'PT' in chain:
					StimulusChain = StimulusChain +chain[0]
			# emparejar == target
			if emparejar:
				actual=0
				# Mouse
				istarget = 0
				for estimulo in emparejar:
					if self.UseMouse:
						if len(emparejar)<=len(self.teclas):
							istarget = self.teclas[actual][0]
						elif len(emparejar)<=len(self.keys):
							istarget = self.keys[actual]
							debug('Warning: Using indiviudal keys, not groups.')
						else:
							debug('Warning: More stimulus than keys.')
							istarget = self.keys[actual]
					imagen=estimulo[posicionimagen]
					PosicionesEstimulo=estimulo[posicionestimulo]
					if LugarEstimulo is None:
						debug('presentar: actual' + str(actual))
						imagenpos=PosicionesEstimulo[actual]
					else:
						debug('presentar: actual' + str(LugarEstimulo))
						imagenpos=PosicionesEstimulo[LugarEstimulo]
					if ((((actual==len(emparejar)-1)) and (not Reverse))
					or  (((actual==0) and Reverse))):
						SSST = self.tiempoemparejar
						SCS  = self.sinpersistenciaemparejar
						SD   = self.retrasoemparejar
					else:
						SSST = 0    # Stimulus Solitarie Show Time
						SCS  = 0    # Stimulus Clear Screen
						SD   = 0    # Stimulus Delay
					# EEG and Time
					TrialIsOK = 0
					if (self.GlobalPresentarEmparejarTakeTimeOK or
						self.GlobalPresentarEmparejarEegSyncSignalOK):
						TrialIsOK = int(estimulo[1] in self.clasesfacil[muestra[0][0]])
						if self.GlobalPresentarEmparejarTakeTimeOK:
							EmparejarTakeTime = TrialIsOK
						if self.GlobalPresentarEmparejarEegSyncSignalOK:
							EmparejarEegSyncSignal = TrialIsOK
					# Sound
					StimulusSound = 0
					for eachstimuluspart in estimulo[3:]:
						if isinstance(eachstimuluspart[0],pygame.mixer.Sound):
							StimulusSound = eachstimuluspart
					if StimulusSound:
						# Don't put delay after last sound
						SoundDelay = 0
						if actual < len(emparejar)-1:
							SoundDelay = StimulusSound[1]
						SSST = copy.copy(SoundDelay+SSST)
						if self.GlobalPresentarEmparejarMaxSSST and (SSST>self.GlobalPresentarEmparejarMaxSSST):
							SSST = copy.copy(self.GlobalPresentarEmparejarMaxSSST)
						StimulusChain.append((STIMULUSTYPESOUND, 0, 0 , StimulusSound[0], 0))
						StimulusChain.append((STIMULUSTYPEIMAGE, copy.copy(EmparejarTakeTime), copy.copy(EmparejarEegSyncSignal), imagen, imagenpos,SSN,copy.copy(SSST),SCS,SD,copy.copy(istarget)))
					else:
						StimulusChain.append((STIMULUSTYPEIMAGE, copy.copy(EmparejarTakeTime), copy.copy(EmparejarEegSyncSignal), imagen, imagenpos,SSN,copy.copy(SSST),SCS,SD,copy.copy(istarget)))
					if EmparejarTakeTime and self.GlobalPresentarEmparejarTakeTimeOnlyOne:
						EmparejarTakeTime = 0
					if EmparejarEegSyncSignal and self.GlobalPresentarEmparejarEegSyncSignalOnlyOne:
						EmparejarEegSyncSignal = 0
					actual+=1
				posicionestimulo+=IncPosicionEstimulo
			# PO = Post
			for chain in ExternalChains:
				if 'PO' in chain:
					StimulusChain = StimulusChain + chain[0]
			for chain in ExternalChains:
				if 'S' in chain:
					muestra.append(chain[0])
				if 'R' in chain:
					relacion.append(chain[0])
				if 'T' in chain:
					emparejar.append(chain[0])
			if Reverse:
				StimulusChain.reverse()
			FinalStimulusChain = AvisoChain + StimulusChain
			if self.PresentarGetStimulusChain:
				return FinalStimulusChain
			else:
				selectedkey, tiempo, TiempoLimite = self.show(FinalStimulusChain)
			if selectedkey and self.Result:
				posicion=0
				for cadaconjunto in self.teclas:
					if selectedkey in cadaconjunto:
						teclaelegida = posicion + 1
						if len(emparejar) == len(self.teclas):
							estimuloelegido = self.StimulusName(emparejar[posicion],LugarEstimulo,SaveStimulusPosition)
						## print teclaacierto,' == ',selectedkey
						if not (teclaacierto is None):
							if isinstance(teclaacierto, list):
								resultado = int(teclaelegida in teclaacierto)
							else:
								resultado = int(teclaacierto == teclaelegida)
							## print resultado, teclaacierto,' == ',selectedkey
						elif self.clasesfacil:
							if relacion:
								resultado=int(relacion[0][0]+emparejar[posicion][0] in self.clasesfacil[muestra[0][0]])
							else:	
								resultado=int(emparejar[posicion][0] in self.clasesfacil[muestra[0][0]])
						break
					posicion+=1
			if ((not selectedkey) and self.tiempolimite and TiempoLimite):
				if not (teclaacierto is None):
					resultado = int(teclaacierto == teclaelegida == 0)
					if resultado:
						ThisTrialFeedback = 0
			if (teclaelegida==0) and self.NoAnswerNoFeedback:
				ThisTrialFeedback = 0
			# Feedback
			if ThisTrialFeedback:
				if self.NoAnswerFeedBack:
					self.FeedBack(resultado,AnswerKey=teclaelegida)
				else:
					self.FeedBack(resultado)
		# Saving the result
		linearesultado=[]
		if len(emparejar) > 1:
			linearesultado.append(estimuloelegido)
		if muestra:
			linearesultado.append(self.StimulusName(muestra[0],LugarEstimulo,SaveStimulusPosition))
		if relacion:
			linearesultado.append(self.StimulusName(relacion[0],LugarEstimulo,SaveStimulusPosition))
		StimulusNumber=0
		for cadauno in emparejar:
			linearesultado.append(self.StimulusName(cadauno,LugarEstimulo,SaveStimulusPosition))
			StimulusNumber+=1
		if StimulusNumber > self.StimulusNumber:
			self.StimulusNumber = StimulusNumber
		elif StimulusNumber < self.StimulusNumber:
			for ExtraBlankStimulus in range(self.StimulusNumber - StimulusNumber):
				linearesultado.append('')
		if self.checknodaldistance:
			linearesultado.append(self.distancianodal(muestra[0][0],emparejar))
		if isinstance(self.retraso,list) or self.IncludePresentarRetrasoMuestra:
			self.IncludePresentarRetrasoMuestra = 1
			linearesultado.append(RetrasoMuestra)
		if isinstance(self.retrasorelacion,list) or self.IncludePresentarRetrasoRelacion:
			self.IncludePresentarRetrasoRelacion = 1
			linearesultado.append(RetrasoRelacion)
		# Really Saving Results
		if self.PresentarSaveResultsNow:
			if self.PresentarFullResult and self.IncludePresentarFullResultTime:
				if isinstance(self.PresentarFullResult,tuple):
					linearesultado.append(self.PresentarFullResult[1][1][0])
				elif isinstance(self.PresentarFullResult,list): 
					for OneFullResult in self.PresentarFullResult:
						linearesultado.append(OneFullResult[1][1][0])
			self.SaveResult(resultado,tiempo,TiempoLimite,teclaelegida,linearesultado)
			self.PresentarFullResult = []
		else:
			if self.PresentarFullResult:
				if isinstance(self.PresentarFullResult,tuple):
					self.PresentarFullResult = [(resultado,tiempo,TiempoLimite,teclaelegida,linearesultado),self.PresentarFullResult]
				elif isinstance(self.PresentarFullResult,list): 
					self.PresentarFullResult.append((resultado,tiempo,TiempoLimite,teclaelegida,linearesultado))
				if self.IncludePresentarFullResultTime<len(self.PresentarFullResult):
					self.IncludePresentarFullResultTime = len(self.PresentarFullResult)
			else:
				self.PresentarFullResult = (resultado,tiempo,TiempoLimite,teclaelegida,linearesultado)
		return resultado

	def SaveResult(self,resultado,tiempo,TiempoLimite,teclaelegida,extra):
		"""Save results.
		Parameters:
		
		resultado: 1 or 0 (good/bad).
		tiempo: time in miliseconds.
		TiempoLimite: 1 dead line time reached.
		teclaelegida: Order number of selected key in self.teclas
		extra: Extra data (list), like stimulus showed, selected, nodal distance.
		
		Returns nothing.
		"""
		debug('SaveResult')
		# Saving the result
		linearesultado=[]
		if grupo:
			linearesultado=[grupo]
		if Condition:
			linearesultado.append(Condition)
		linearesultado.append(codigosujeto)
		linearesultado.append(generosujeto)
		linearesultado.append(edadsujeto)
		if self.fase:
			linearesultado.append(self.fase)
		if self.bloque:
			linearesultado.append(self.bloque)
		linearesultado.append(self.numero)
		if self.Result:
			linearesultado.append(resultado)
		if self.StimulusTakeTimeMaxCount:
			linearesultado=linearesultado+tiempo[0]
			if self.StimulusTakeTimeMaxCount>len(tiempo[0]):
				for agregado in range(self.StimulusTakeTimeMaxCount-len(tiempo[0])):
					linearesultado.append(-1)
		if self.LastTakeTime:
			linearesultado=linearesultado+tiempo[1]
		linearesultado=linearesultado+[TiempoLimite,teclaelegida]
		linearesultado=linearesultado+extra
		if soundrecorderpid:
			linearesultado.append(SoundFileName)
		STRlinearesultado=[]
		for cadauno in linearesultado:
			if isinstance(cadauno,basestring):
				STRlinearesultado.append(cadauno)
			else:
				STRlinearesultado.append(str(cadauno))
		self.resultados.append(STRlinearesultado)

	def CalculeResult(self,result,criteria=None,output="num",multply=1,operation="average"):
		"""Calcula el porcentaje de aciertos.
		
		Parametros:
		result: Columna de resultados, la primera es 0.
		criteria: [(column,operand,value),(column,operand,value)...]
			column: Columna en la que se verifica el valor.
			operand: Python lógical operand as string.
			value: Valor de que debe coincidir en column, para que sea sumada la columan result.
		operation: average, sum or count (defalut average)
		multiply: result will be multiply by this (default 1).
		output: str for string, num for numeric or dec for decimal (default is num)
		
		return Un porcentaje de aciertos como cadena de texto.
		"""
		Aciertos = decimal.Decimal('0.0')
		Trials = decimal.Decimal('0.0')
		Trues = decimal.Decimal('0.0')
		Resultado = decimal.Decimal('0.0')
		column = 0
		operand = 1
		value = 2
		for linea in self.resultados:
			CompliedCriteria = 0
			if not (criteria is None):
				for criterion in criteria:
					if eval('"'+str(linea[criterion[column]])+'"'+criterion[operand]+'"'+str(criterion[value])+'"'):
						CompliedCriteria += 1
			if (CompliedCriteria==len(criteria)) or (criteria is None):
				Trials+=decimal.Decimal('1.0')
				try:
					Aciertos+=decimal.Decimal(int(linea[result]))
				except:
					pass
				if linea[result]!='0':
					Trues += decimal.Decimal('1.0')
		if Trials:
			if operation=="average":
				Resultado = decimal.Decimal(Aciertos)/decimal.Decimal(Trials)*decimal.Decimal(multply)
			if operation=="hits":
			    Resultado = decimal.Decimal(Trues)/decimal.Decimal(Trials)*decimal.Decimal(multply)
			elif operation=="sum":
				Resultado = Aciertos
			elif operation=="count":
				Resultado = Trials
			if output=="str":
				try:
					promedio = fpformat.fix(float(fpformat.fix(Resultado,2).split('"')[1]),2)
				except IndexError:
					promedio = fpformat.fix(float(fpformat.fix(Resultado,2).split("'")[1]),2)
			else:
				promedio = Resultado
		else:
			if output=="str":
				promedio = 'N/A'
			elif output=="num":
				promedio = 'NaN'
			elif output=="dec":
				promedio = decimal.Decimal(0)
		return promedio

	def AverangeResult(self,result,criteria=None,output="str"):
		"""Calcula el porcentaje de aciertos.
		
		Parametros:
		result: Columna de resultados, la primera es 0.
		criteria: [(column,operand,value),(column,operand,value)...]
		column: Columna en la que se verifica el valor.
		operand: Python logical operand as string.
		value: Valor de que debe coincidir en column, para que sea sumada la columan result.
		
		return Un porcentaje de aciertos como cadena de texto.
		"""
		debug('AverangeResult')
		return self.CalculeResult(result,criteria,output,multply=100)

	def FeedBack(self, resultado,tiempofeedback=None,AnswerKey=None,NoAnswerFeedBack=None):
		"""Show Feedback.
		
		Parameters:
		resultado: 0 incorrect, 1 correct.
		tiempofeedback: Feedback Time.
		AnswerKey: Key pressed
		NoAnswerFeedBack: Show No Response Feedback.
		
		Returns nothing.
		"""
		debug('FeedBack')
		pygame.time.delay(self.FeedBackDelay)
		feedbacksonido=0
		if tiempofeedback is None:
			tiempofeedback = self.FeedBackShowTime
		if NoAnswerFeedBack is None:
			NoAnswerFeedBack = self.NoAnswerFeedBack
		# Set Message & Sound
		if NoAnswerFeedBack and not AnswerKey is None and not AnswerKey:
			if self.NoAnswer.imagen:
				feedback=self.NoAnswer.imagen
			else:
				feedback=self.NoAnswer.texto
			if self.NoAnswer.sonido:
				feedbacksonido=self.NoAnswer.sonido
		else:
			if resultado:
				if self.bien.imagen:
					feedback=self.bien.imagen
				else:
					feedback=self.bien.texto
				if self.bien.sonido:
					feedbacksonido=self.bien.sonido
			else:
				feedback=self.mal.texto
				if self.mal.imagen:
					feedback=self.mal.imagen
				else:
					feedback=self.mal.texto
				if self.mal.sonido:
					feedbacksonido=self.mal.sonido
		# Show Feedback
		screen.blit(feedback[0],feedback[1])
		if feedbacksonido:
			feedbacksonido.play()
		pygame.display.flip()
		pygame.time.delay(tiempofeedback)

	def StimulusName(self, Stimulus, StimulusPlace, SaveStimulusPosition):
		"""Get Back a Valid Stimulus Name.
		Parameters:
		Stimulus: An Stimulus.
		StimulusPlace: Place of the Stimulus in Screen, in nBackSpatial Experiment.
		
		Returns: Valid Stimulus Name As String.
		"""
		debug('StimulusName')
		if (Stimulus[0]==Stimulus[1]) or (Stimulus[0]=='==' and Stimulus[1]=='='):
			# Traditional stimulus name.
			NameOfStimulus = Stimulus[1]
		else:
			# Stimulus Name and Alias must be saved, if they are diferent
			NameOfStimulus = Stimulus[0]+"~"+Stimulus[1]
		if (not (StimulusPlace is None)) and SaveStimulusPosition:
			# Stimulus Place of nBackSpatial experimen must be saved.
			NameOfStimulus = NameOfStimulus + "@" + str(StimulusPlace+1)
		return NameOfStimulus

	def distancianodal(self,muestra,emparejar):
		"""Solo valido para entrenamiento en series lineales.
		Valid only in lineal series training.
		
		This method is used by intento.presentar() in order to calculate nodal distance.
		
		Parameters:
		muestra: Sample stimulus.
		emparejar: Matching stimulus.
		
		Get back the nodal distance between both.
		
		Example:
		Serie is A -> B -> C -> D -> E
		
		distancianodal(A,A) is -1
		distancianodal(A,B) is 0
		distancianodal(A,C) is 1
		distancianodal(A,D) is 2
		and so on."""
		debug('distancianodal')
		estimulo=""
		for cadauno in emparejar:
			if cadauno[0] in self.clasesfacil[muestra]:
				estimulo=cadauno[0]
		try:
			Nmuestra=self.clasesfacil[muestra].index(muestra)
		except ValueError:
			Nmuestra=-1
		try:
			Nestimulo=self.clasesfacil[muestra].index(estimulo)
		except ValueError:
			Nestimulo=-1
		if Nmuestra==-1 or Nestimulo==-1:
			distancia="Error"
		else:
			distancia=abs(Nmuestra-Nestimulo)-1
		return distancia

	def show(self,stimulus):
		"""Show stimulus and waits for an answer.
		Parameters:
		stimulus: Stimulus as list of tuples.
		
		Stimulus Format:
		
		(StimulusType, TakeTime, eegsyncsignal, image, image position, shownow, solitarie show time, clear screen, delay, istarget)
		
		or
		
		(StimulusType, TakeTime, eegsyncsignal, video, video position, shownow, solitarie show time, clear screen, delay, loop, istarget)
		
		or
		
		(StimulusType, TakeTime, eegsyncsignal, sound, delay)
		
		Where:
		
		StimulusType: STIMULUSTYPEIMAGE is image, STIMULUSTYPEVIDEO is video, and STIMULUSTYPESOUND is sound.
		TakeTime: Take time in this stimulus, 0 no, 1 yes.
		eegsyncsignal: Send EEG sync signal in this stimulus, 0 no, 1 yes.
		image: must be a surface.
		image position: is a valid pygame rect.
		shownow: 1 Show Stimulus inmediatly, independently of 'solitarie show time'.
		solitarie show time: time to show de stimulus alone in miliseconds.
		clear screen: 1 clear screen and 0 no.
		delay: delay to next stimulus presentation in miliseconds.
		sound: must be a sound loaded with cargarsonido.
		video: A Movie.
		video position: is a valid pygame rect.
		loop: Video loop. 0 is infinite.
		
		Note: shownow don't work with videos.  Always are played inmediatly.
		
		Returns: Key pressed, time, time stop.
		
		Where:
		
		Key pressed: is a PyGame key code.
		time: between last stimulus presentation and response in miliseconds.
		time stop: 1 dead line time reached, 0 exists response."""
		global debugging
		debug('show')
		selectedkey=0
		self.MouseSelectedKey = 0
		TiempoLimite=0
		tiempo = []
		# Estimulo
		StimulusType = 0
		TakeTime = 1
		EegSyncSignal = 2
		imagen = sonido = video = sprite = 3
		posimagen = 4
		mostrarya = 5
		tiempomuestra = 6
		sinpersistencia = 7
		loop = 9
		try:
			debug('show: self.fase:'+self.fase+', self.bloque:'+self.bloque+', self.numero: '+str(self.numero))
		except:
			pass
		if quickrandomresponse:
			if self.IncrementNumero:
				self.numero += 1
			tiempo.append([])
			for estimulo in stimulus:
				if estimulo[TakeTime]:
					tiempo[0].append([-1])
			tiempo.append([-1])
			debug('keys: ' + str(self.keys))
			if self.keys:
				return [random.choice(self.keys), tiempo, TiempoLimite]
			else:
				return [0, tiempo, TiempoLimite]
		if self.CleanScreenBeforeStimulus:
			cleanscreen()
		TimeTrack = []
		NotEarlyResponse = 1
		antes = 0
		seguir=1
		videos = []
		backupvideos = []
		puertoserial = 0
		puertoserialfinish = 0
		global NextSpritUpdate
		NextSpritUpdate = 0
		BackSurface = screen.copy()
		BackSurfaceTemp = screen.copy()
		BlackScreen = screen.copy()
		if self.CleanScreenBeforeStimulus:
			BlackScreen.fill(background)
		ExistSprits = 0
		allSprites = pygame.sprite.Group()
		Targets = []
		# Sound Recorder
		if SoundRecorder:
			restartsoundrecorder()
		pygame.time.delay(self.espera)
		pygame.event.clear()
		# Mouse
		if self.UseMouse:
			ShowMouse(1)
		# Stimulus Loop
		debug('show: stimulus: '+str(stimulus))
		for estimulo in stimulus:
			if estimulo[StimulusType]==STIMULUSTYPEIMAGE:
				# Image
				retraso = 8
				istarget = 9
				# Mouse
				if estimulo[istarget]:
					Targets.append({'rect': estimulo[posimagen], 'key': estimulo[istarget]})
				BackSurfaceTemp.blit(estimulo[imagen], estimulo[posimagen])
				if estimulo[mostrarya] or estimulo[tiempomuestra]:
					clock.tick()
					screen.blit(BackSurfaceTemp, (0,0))
					if ExistSprits:
						allSprites.clear(screen, BackSurfaceTemp)
						allSprites.update()
						allSprites.draw(screen)
						NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
					pygame.display.flip()
					screen.blit(BackSurfaceTemp, (0,0))
			elif estimulo[StimulusType]==STIMULUSTYPESOUND:
				# Sound
				retraso = 4
				estimulo[sonido].play()
			elif estimulo[StimulusType]==STIMULUSTYPEVIDEO:
				# Video
				retraso = 8
				istarget = 10
				# Mouse
				if estimulo[istarget]:
					Targets.append({'rect': estimulo[posimagen], 'key': estimulo[istarget]})
				videos.append(estimulo[video])
				videos[len(videos)-1].set_display(screen,estimulo[posimagen])
				videos[len(videos)-1].rewind()
				videos[len(videos)-1].play(estimulo[loop])
				if not estimulo[sinpersistencia]:
					backupvideos.append(estimulo)
			elif ((estimulo[StimulusType]==STIMULUSTYPESPRIT)
			or    (estimulo[StimulusType]==STIMULUSTYPEACTIO)):
				retraso = 8
				istarget = 9
				# Mouse
				if estimulo[istarget]:
					Targets.append({'rect': estimulo[posimagen], 'key': estimulo[istarget]})
				ExistSprits = 1
				if estimulo[StimulusType]==STIMULUSTYPESPRIT:
					allSprites.add(estimulo[sprite])
				elif estimulo[StimulusType]==STIMULUSTYPEACTIO:
					for cadasprite in estimulo[sprite]:
						allSprites.add(copy.copy(cadasprite))
				BackSurfaceTemp = BackSurface.copy()
				if estimulo[mostrarya] or estimulo[tiempomuestra]:
					clock.tick()
					screen.blit(BackSurfaceTemp, (0,0))
					if ExistSprits:
						allSprites.clear(screen, BackSurfaceTemp)
						allSprites.update()
						allSprites.draw(screen)
						NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
					pygame.display.flip()
					screen.blit(BackSurfaceTemp, (0,0))
			else:
				debugging = 1
				debug("*** Error: Stimulus Error in intento.Show()")
				debug("\tStimulus: ", estimulo)
				sys.exit()
			if estimulo[TakeTime]:
				TimeTrack.append(pygame.time.get_ticks())
			# EEG
			if estimulo[EegSyncSignal] and eegsync and SerialLoaded:
				if not puertoserial:
					puertoserial = serial.Serial(eegsyncport,eegbaudrate)
				puertoserialfinish = pygame.time.get_ticks() + eegsyncmintime
			# Solitarie show time
			if (estimulo[StimulusType]==STIMULUSTYPEIMAGE
				or estimulo[StimulusType]==STIMULUSTYPEVIDEO
				or estimulo[StimulusType]==STIMULUSTYPESPRIT
				or estimulo[StimulusType]==STIMULUSTYPEACTIO):
				if estimulo[tiempomuestra]:
					pygame.event.pump()
					ahora = pygame.time.get_ticks()
					limite = ahora + estimulo[tiempomuestra]
					if NotEarlyResponse:
						event = pygame.event.poll()
						if self.TakeResponseFromStart and event.type == KEYDOWN and event.key in self.keys:
							NotEarlyResponse = 0
							despues = ahora
					while (((not (self.TakeResponseFromStart and event.type == KEYDOWN
						and event.key in self.keys)) or self.ShowAllStimulus)
						and limite>ahora):
						pygame.event.pump()
						ahora = pygame.time.get_ticks()
						if NotEarlyResponse:
							event = pygame.event.poll()
							if self.TakeResponseFromStart and event.type == KEYDOWN and event.key in self.keys:
								NotEarlyResponse = 0
								despues = ahora
						# EEG
						if puertoserial and puertoserialfinish<=pygame.time.get_ticks():
							puertoserial.flushOutput()
							puertoserial.close()
							puertoserial = 0
						# Actualizar la pantalla si hay sprites
						if ExistSprits and NextSpritUpdate <= pygame.time.get_ticks():
							##clock.tick()
							screen.blit(BackSurfaceTemp, (0,0))
							allSprites.clear(screen, BackSurfaceTemp)
							allSprites.update()
							allSprites.draw(screen)
							NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
							pygame.display.flip()
							screen.blit(BackSurfaceTemp, (0,0))
				# Sin Persistencia
				if estimulo[sinpersistencia]:
					if estimulo[StimulusType]==STIMULUSTYPEVIDEO:
						videos[len(videos)-1].stop()
						videos[len(videos)-1] = None
					elif estimulo[StimulusType]==STIMULUSTYPESPRIT:
						allSprites.remove(estimulo[sprite])
						ExistSprits = len(allSprites)
					##clock.tick()
					screen.blit(BlackScreen, (0,0))
					if ExistSprits:
						allSprites.clear(screen, BlackScreen)
						allSprites.update()
						allSprites.draw(screen)
						NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
					pygame.display.flip()
					screen.blit(BlackScreen, (0,0))
					BackSurfaceTemp = BackSurface.copy()
				else:
					BackSurface = BackSurfaceTemp.copy()
			# End - Solitarie show time
			# Delay
			if estimulo[retraso] and (self.ShowAllStimulus or NotEarlyResponse):
				pygame.event.pump()
				ahora = pygame.time.get_ticks()
				limite = ahora + estimulo[retraso]
				if NotEarlyResponse:
					event = pygame.event.poll()
					if self.TakeResponseFromStart and event.type == KEYDOWN and event.key in self.keys:
						NotEarlyResponse = 0
						despues = ahora
				while (((not (self.TakeResponseFromStart and event.type == KEYDOWN
					and event.key in self.keys)) or self.ShowAllStimulus)
					and limite>ahora):
					pygame.event.pump()
					ahora = pygame.time.get_ticks()
					if NotEarlyResponse:
						event = pygame.event.poll()
						if self.TakeResponseFromStart and event.type == KEYDOWN and event.key in self.keys:
							NotEarlyResponse = 0
							despues = ahora
					# EEG
					if puertoserial and puertoserialfinish<=pygame.time.get_ticks():
						puertoserial.flushOutput()
						puertoserial.close()
						puertoserial = 0
					# Actualizar la pantalla si hay sprites
					if ExistSprits and NextSpritUpdate <= pygame.time.get_ticks():
						##clock.tick()
						screen.blit(BackSurface, (0,0))
						allSprites.clear(screen, BackSurface)
						allSprites.update()
						allSprites.draw(screen)
						NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
						pygame.display.flip()
						screen.blit(BackSurface, (0,0))
			# End - Delay
			if not (NotEarlyResponse or self.ShowAllStimulus):
				break
		# End - Stimulus Loop
		if NotEarlyResponse or self.ShowAllStimulus:
			clock.tick()
			screen.blit(BackSurface, (0,0))
			if ExistSprits:
				allSprites.clear(screen, BackSurface)
				allSprites.update()
				allSprites.draw(screen)
			pygame.display.flip()
			screen.blit(BackSurface, (0,0))
		pygame.event.clear()
		antes = pygame.time.get_ticks()
		limite = antes + self.tiempolimite
		# EEG
		if self.LastEegSyncSignal and eegsync and SerialLoaded:
			if not puertoserial:
				puertoserial = serial.Serial(eegsyncport,eegbaudrate)
			puertoserialfinish = pygame.time.get_ticks() + eegsyncmintime
		## pygame.time.delay(500)
		## pygame.image.save(screen, "screen-"+str(self.numero)+".bmp")
		while seguir:
			if NotEarlyResponse:
				pygame.event.pump()
				despues = pygame.time.get_ticks()
				event = pygame.event.poll()
				if randomresponse:
					pygame.event.post(pygame.event.Event(KEYDOWN, key=random.choice(self.keys)))
				while (not(event.type in EVENTS) and event.type != QUIT
					and ((not self.tiempolimite) or (limite>despues))):
					pygame.event.pump()
					despues = pygame.time.get_ticks()
					event = pygame.event.poll()
					# EEG
					if puertoserial and puertoserialfinish<=pygame.time.get_ticks():
						puertoserial.flushOutput()
						puertoserial.close()
						puertoserial = 0
					# Actualizar la pantalla si hay sprites
					if ExistSprits and NextSpritUpdate <= pygame.time.get_ticks():
						##clock.tick()
						##SpriteTimeBefore = pygame.time.get_ticks()
						screen.blit(BackSurface, (0,0))
						allSprites.clear(screen, BlackScreen)
						allSprites.update()
						allSprites.draw(screen)
						NextSpritUpdate = pygame.time.get_ticks() + self.SpritUpdateDelay
						pygame.display.flip()
						screen.blit(BackSurface, (0,0))
						##print('Show:',pygame.time.get_ticks() - SpriteTimeBefore)
			if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
				for Video in videos:
					Video.stop()
					Video = None
				self.salir()
				videos=[]
				for estimulo in backupvideos:
					videos.append(estimulo[video])
					videos[len(videos)-1].set_display(screen,estimulo[posimagen])
					videos[len(videos)-1].rewind()
					videos[len(videos)-1].play(estimulo[loop])
			if event.type == KEYDOWN and event.key in self.keys:
				selectedkey = event.key
				seguir=0
			if (not (event.type == KEYDOWN) and self.tiempolimite and limite<=despues):
				TiempoLimite=1
				seguir=0
			if event.type == MOUSEBUTTONDOWN and self.GetMouseKey(event,Targets):
				selectedkey = self.MouseSelectedKey
				seguir=0
		# Ending Trial Tasks
		for Video in videos:
			Video.stop()
			Video = None
		if self.UseMouse:
			ShowMouse(0)
		if self.CleanScreenAfterResponse:
			cleanscreen()
		# EEG
		if puertoserial:
			# Waits trasmision time to finish serial connection.
			while puertoserialfinish>pygame.time.get_ticks():
				pass
			puertoserial.flushOutput()
			puertoserial.close()
			puertoserial = 0
		# Results
		if self.StimulusTakeTimeMaxCount<len(TimeTrack):
			if self.resultados:
				debugging = 1
				debug('*** Error: StimulusTakeTimeMaxCount modificado luego de la primera asignacion.  Error en archivo de Registro.')
				debug('Inicialice la variable intento.StimulusTakeTimeMaxCount = '+str(len(TimeTrack)))
				sys.exit()
			self.StimulusTakeTimeMaxCount=len(TimeTrack)
		tiempo.append([])
		if TimeTrack:
			for cadatiempo in TimeTrack:
				tiempo[0].append(despues - cadatiempo)
		if self.LastTakeTime:
			tiempo.append([despues - antes])
		else:
			tiempo.append([-1])
		if self.IncrementNumero:
			self.numero += 1
			debug('show: self.numero: '+str(self.numero))
		return [selectedkey, tiempo, TiempoLimite]

	def GetMouseKey(self, Event, targets):
		"""
		Used internally
		"""
		self.MouseSelectedKey = 0
		for target in targets:
			if target['rect'].collidepoint(Event.pos):
				if 'button' in target:
					if target['button']==Event.button:
						self.MouseSelectedKey = target['key']
				elif self.MouseButton==Event.button:
					self.MouseSelectedKey = target['key']
		return self.MouseSelectedKey

	def makephrase(self, phrase, good=1, sounds=[], time=None, sumsoundtime=1, fontdivisor=0,
		fontsize=0, fontfile='',homosound=0, sep=' ', soundfolder='Palabras',soundfiletype='.ogg',
		soundnames=[],finaldot=0,DALS=None,images=[],homoimage=0,imagefolder='Imagenes',
		imagefiletype='.png',moviefiletype='.mpg',actionsprite=[],SpritDelay=0,IALP=1,
		IAVP=1,showtext=1,colorkey=None,convert=0,TTEW=0,correct=0,ErrorType=None,
		NoSaveResult=0, WaitResponse=0, NoLoop=0, ExtraData={},WordByWord=None,
		CleanLastWordByWord=None,BreakWord=0):
		"""Make phrases word by word.
		Display it with showphrases().
		
		Parameters:
		phrase: Text, as string.
		good: 1 this phrase is correct, 0 incorrect.
		sounds: Sound files for each word in phrase, in the same order.
		time: Time to show each word before the next one, in miliseconds. (default 250)
		sumsoundtime: 1 sum sound length time to 'time', if 0, no.  Default 1.
		homosound: The name of each sound file is each word in phrase (lower case).
		sep: Word separator.  Space by default.
		soundfolder: Sound files location.  Default 'Palabras'.
		soundfiletype: Sounds must be '.ogg' or '.wav' file type.  Default '.ogg'.
		finaldot: 1 show a final point. Default is 0 (False).
		DALS: Delay After Last Sound (or Text Stimulus). Default is 0 (False).
		images: Image files for each word in phrase, in the same order.
		homoimage: The name of each image file is each word in phrase (lower case).
		imagefolder: Images folder.  Default is 'Imagenes'.
		imagefiletype: Image file type.  Default is '.png'.
		showtext: 1 show text, 0 no. Default is 1.
		moviefiletype= default is '.mpg'
		SpritDelay: Default is 0.  It can be a list, for each image position.
					Try to use intento.SpritUpdateDelay to set optimus sprit speed.  Is better.
		IALP: Image Absolute Lateral Pos if 1. 0 is relative lateral pos.  Default is 1.
		      Center image lateraly in word.
		IAVP: Image Absolute Vertial Pos if 1. 0 is relative vertial pos.  Default is 1.
		      Puts image exactly over text line.
		colorkey: List of/or transaparency color key index, by word order.  Default is None.
				A number is automatic, for all, or a list with each value by word.
		convert: Convert image to Display type, Default is 0 (False).
				A number is automatic, for all, or a list with each value by word.
		TTEW: Take time for every word. Default is 0 (false).
		correct: Is the correct phrase, is other  phrase object (0).
		ErrorType: If your experiment test gramatical or semantical error, code it here (None).
		NoSaveResult: Used internaly by show1phrase for feedback (0)
		WaitResponse=: Used internaly by show1phrase for feedback (0)
		NoLoop: Used internaly by show1phrase for feedback (0)
		ExtraData: Dictionary with anything, ignored by pyexpsin ({})
		WordByWord: 1 show phrase Word by Word (0).
		CleanLastWordByWord: 1 clean last word in word by word (0).
				
		Special characters:
		
		'~': Image/Video/Sprite name is the complete phrase.
		'@': Take time and send EEG sync signal in this word beginning.
		'^': Image/Video/Sprite must be centered horizontaly.
		'>': Sprite is showed in foward and backward.
		'<': Sprite is showed in reverse
		'|': Image/Sprite is flipped horizontaly, left -> right.
		'-': Image/Sprite is flipped verticaly, top -> bottom.
		'*': Image/Sprite is rotated by 90 degrees (You can use more than one).
		
		Examples:
		
		Only Text:
		intento.makephrase(u'I love you')
		
		Sound file are each word.
		intento.makephrase(u'I love you', homo=1)
		
		Sound file name is diferent:
		intento.makephrase(u'I love you',['1','2','3'])
		
		All phrase in a line, and a sound file:
		intento.makephrase(u'I love you', homo=1, sep='')
		
		Image name is complete phrase, will be centered, rotated 180 degrees,
		and if it an sprite, will be showed in reverse.
		Love will be tracked by time and EEG sync signal
		intento.makephrase(u'^<I** @love you', homoimage=1)
		
		Returns a frase to show with showphrases"""
		global debugging
		debug(u'makephrase: '+phrase)
		OriginalPhrase = phrase
		self.PhraseErrorType = 1
		##debug('makephrase: '+phrase.encode('ascii','ignore'))
		self.texto([u"Creando estímulos","Por favor, espere."],divisor=15,esperarevento=0)
		if time is None:
			time = self.GlobalPharseTimeBetweenWords
		if DALS is None:
			DALS = self.GlobalPharseDelayAfterLastSound
		if WordByWord is None:
			WordByWord = self.GlobalPharseWordByWord
		if CleanLastWordByWord is None:
			CleanLastWordByWord = self.GlobalPharseCleanLastWordByWord
		#Stimulus Format:
		#[image, image position, shownow, solitarie show time, clear screen, delay, istarget]
		#[sound, delay]
		SN  = 1    # Show Now
		SST = 0    # Solitarie Show Time
		CS  = 0    # Clear Screen
		dotstr = u'.'
		cleanphrase = phrase.replace('~','').replace('@','').replace('^','').replace('<','').replace('>','').replace('-','').replace('|','').replace('*','')
		if finaldot:
			fraseimg, frasepos = self.cargartexto(cleanphrase+dotstr,divisor=fontdivisor)
		else:
			fraseimg, frasepos = self.cargartexto(cleanphrase,divisor=fontdivisor)
		if BreakWord:
			phraseprima = ''
			for letter in phrase:
				phraseprima = phraseprima + letter + sep
			phrase = phraseprima.strip()
		fraselist = phrase.split(sep)
		if correct and not(actionsprite or images):
			images=[]
			correctphrase=correct[0].translate(limpiar)
			correctphraselist = correctphrase.split(sep)
			for word in correctphraselist:
				if '~' in word:
					images.append(correctphrase)
					break
				else:
					images.append(word.translate(limpiar))
			debug('images: '+str(images))
		# Put separator character after each word.
		if not BreakWord:
			for i in range(len(fraselist)):
				if i < (len(fraselist)-1):
					fraselist[i] = fraselist[i] + sep
		itotallateral = len(fraselist)+1
		fraseReturn = []
		left = frasepos[0]
		WordPos = 0
		for palabra in fraselist:
			ImageBaseName = ''
			if '~' in palabra:
				palabra = palabra.replace('~','')
				ImageBaseName = cleanphrase
			EegSyncSignal = 0	
			TakeTime = 0
			if '@' in palabra or TTEW:
				palabra = palabra.replace('@','')
				TakeTime = 1
				EegSyncSignal = 1
			CenterImageHorizontal = 0
			if '^' in palabra:
				palabra = palabra.replace('^','')
				CenterImageHorizontal = 1
			ScriptAction = 'Normal'
			if '>' in palabra:
				palabra = palabra.replace('>','')
				ScriptAction = 'FullCircle'
			if '<' in palabra:
				palabra = palabra.replace('<','')
				ScriptAction = 'Reverse'
			ScriptFlip = [0, 0]
			if '|' in palabra:
				palabra = palabra.replace('|','')
				ScriptFlip[0] = 1
			if '-' in palabra:
				palabra = palabra.replace('-','')
				ScriptFlip[1] = 1
			ScriptRotate = 0.0
			if '*' in palabra:
				ScriptRotate = palabra.count('*')*90.0
				palabra = palabra.replace('*','')
			palabraReturn = []
			sonidoReturn = []
			imagenReturn = []
			WordByWordReturn = []
			# Texto
			if showtext and (images or homoimage or actionsprite):
				totalvertical = 3
				verticalpos = 2
			else:
				totalvertical = 2
				verticalpos = 1
			if WordByWord:
				left = None
			if IAVP:
				img , pos = self.cargartexto(palabra,divisor=fontdivisor,Left=left)
			else:
				img , pos = self.cargartexto(palabra,divisor=fontdivisor,Left=left,totalvertical=totalvertical,verticalpos=verticalpos)
			if WordByWord:
				BlackWord = img.copy()
				BlackWord.fill(background)
				BlackWordPos = copy.copy(pos)
				if WordPos < (len(fraselist)-1) or CleanLastWordByWord:
					WordByWordReturn = (STIMULUSTYPEIMAGE,0,0,BlackWord,BlackWordPos,SN,SST,CS,copy.copy(self.GlobalPharseTimeBetweenWordByWord),0)
			if showtext:
				if not (sounds or homosound or soundnames):
					DelayTime = time
				else:
					DelayTime = 0
				if WordPos < (len(fraselist)-1) or DALS:
					palabraReturn = (STIMULUSTYPEIMAGE,TakeTime,EegSyncSignal,img,pos,SN,SST,CS,copy.copy(DelayTime),0)
				else:
					palabraReturn = (STIMULUSTYPEIMAGE,TakeTime,EegSyncSignal,img,pos,SN,SST,CS,0,0)
				TakeTime = 0
				EegSyncSignal = 0
			# Imagenes
			if images or homoimage or actionsprite:
				if not (colorkey is None):
					if isinstance(colorkey, list):
						if (len(colorkey)-1) >= WordPos:
							thisimagecolorkey = colorkey[WordPos]
						else:
							thisimagecolorkey = None
					else:
						thisimagecolorkey = colorkey
				else:
					thisimagecolorkey = colorkey
				if isinstance(convert, list):
						if (len(convert)-1) >= WordPos:
							thisimageconvert = convert[WordPos]
						else:
							thisimageconvert = 0
				else:
					thisimageconvert = convert
				if isinstance(SpritDelay, list):
					if (len(SpritDelay)-1) >= WordPos:
						thisSpritDelay = SpritDelay[WordPos]
					else:
						thisSpritDelay = 75
				else:
					thisSpritDelay = SpritDelay
				iverticalpos = 1
				itotalvertical = totalvertical
				if not showtext:
					ILAP = IAVP = 0
				ilateralpos = WordPos+1
				if IALP:
					if CenterImageHorizontal:
						ailateralpos = frasepos[0] + (fraseimg.get_width()/2)
					else:
						ailateralpos = pos[0] + (img.get_width()/2)
				else:
					ailateralpos = None
				if IAVP:
					aiverticalpos = pos[1]
				else:
					aiverticalpos = None
				loop = img2 = pos2 = None
				if WordPos<len(images):
					NombreSprit   = str(images[WordPos]).lower().strip()
					NombreVideo   = str(images[WordPos]).lower().strip()+moviefiletype
					NombreImagen  = str(images[WordPos]).lower().strip()+imagefiletype
				elif homoimage:
					if ImageBaseName:
						NombreSprit  = str(ImageBaseName).lower().strip()
						NombreVideo  = str(ImageBaseName).lower().strip()+moviefiletype
						NombreImagen = str(ImageBaseName).lower().strip()+imagefiletype
					else:
						NombreSprit  = str(palabra).lower().strip()
						NombreVideo  = str(palabra).lower().strip()+moviefiletype
						NombreImagen = str(palabra).lower().strip()+imagefiletype
				if not (sounds or homosound or soundnames):
					DelayTime = time
				else:
					DelayTime = 0
				if images or homoimage:
					if os.access(imagefolder+os.sep+NombreSprit,os.F_OK):
						img2 = SpriteMovie(NombreSprit, thisSpritDelay,imagefolder,itotalvertical,iverticalpos,itotallateral,ilateralpos,aiverticalpos,ailateralpos,ScriptAction,ScriptFlip,ScriptRotate)
						imagenReturn = (STIMULUSTYPESPRIT,TakeTime,EegSyncSignal,img2,pos2,SN,SST,CS,copy.copy(DelayTime),0,0)
					else:
						if not WordPos:
							debug('Sprite not Found: '+NombreSprit)
					if (img2 is None) and ShowVideo and os.access(imagefolder+os.sep+NombreVideo,os.F_OK):
						img2 , pos2 = self.cargarvideo(NombreVideo,imagefolder,itotalvertical,iverticalpos,itotallateral,ilateralpos,aiverticalpos,ailateralpos)
						if not (img2 is None):
							loop = 0
							imagenReturn = (STIMULUSTYPEVIDEO,TakeTime,EegSyncSignal,img2,pos2,SN,SST,CS,copy.copy(DelayTime),loop,0)
					if (img2 is None) and os.access(imagefolder+os.sep+NombreImagen,os.F_OK):
						img2 , pos2 = self.cargarimagen(NombreImagen,imagefolder,itotalvertical,iverticalpos,itotallateral,ilateralpos,aiverticalpos,ailateralpos,thisimagecolorkey,convert)
						imgtmp = pygame.transform.flip(img2, ScriptFlip[0], ScriptFlip[1])
						if ScriptRotate:
							img2 = pygame.transform.rotate(imgtmp, ScriptRotate)
						else:
							img2 = imgtmp
						imagenReturn = (STIMULUSTYPEIMAGE,TakeTime,EegSyncSignal,img2,pos2,SN,SST,CS,copy.copy(DelayTime),0)
				# Action Sprite
				#def __init__(self, Image, Action, Delay=5,totalvertical=2,
				#verticalpos=1,totallateral=2,lateralpos=1,absoluteverticalpos=None,
				#absolutelateralpos=None,ScriptAction='Normal',colorkey=None):
				if len(actionsprite)>WordPos:
					img2 = []
					for ThisSprite in actionsprite[WordPos]:
						ThisSpriteImage, ThisSpriteAction = ThisSprite
						ThisActionSprite = ActionSprite(ThisSpriteImage,ThisSpriteAction,thisSpritDelay,itotalvertical,iverticalpos,itotallateral,ilateralpos,aiverticalpos,ailateralpos,ScriptAction)
						if sys.platform[0:3]=="win":
							img2.append(ThisActionSprite)
						else:
							img2.insert(0,ThisActionSprite)
					imagenReturn = (STIMULUSTYPEACTIO,TakeTime,EegSyncSignal,img2,pos2,SN,SST,CS,copy.copy(DelayTime),0,0)
				if not (img2 is None):
					TakeTime = 0
					EegSyncSignal = 0
			# Sonido
			if sounds or homosound or soundnames:
				if WordPos<len(sounds):
					sonido = self.cargarsonido(str(sounds[WordPos]).lower().strip()+soundfiletype,soundfolder)
				elif homosound:
					sonido = self.cargarsonido(str(palabra).lower().strip()+soundfiletype,soundfolder)
				elif WordPos<len(soundnames):
					if isinstance(soundnames,(list,tuple)):
						sonido = soundnames[WordPos]
					elif isinstance(soundnames,dict):
						try:
							sonido = soundnames[palabra.strip().lower()]
						except KeyError:
							debugging = 1
							mensaje = ["Objeto de sonido",palabra.strip(),
								"no encontrado.","Imposible continuar","",
								"Para salir presione:","La barra espaciadora"]
							self.texto(mensaje)
							debug('* Error: El archivo de sonido de la palabra "'+palabra.strip()+'" no fue cargado.')
							raise
				try:
					SoundLength = int(sonido.get_length() * 1000)
				except AttributeError:
					SoundLength = None
				if not (SoundLength is None):
					if sumsoundtime:
						Delay = int(time + SoundLength)
					else:
						Delay = time
					if WordPos < (len(fraselist)-1):
						sonidoReturn = (STIMULUSTYPESOUND,TakeTime,EegSyncSignal,sonido,copy.copy(Delay))
					else:
						if finaldot or DALS:
							sonidoReturn = (STIMULUSTYPESOUND,TakeTime,EegSyncSignal,sonido,copy.copy(SoundLength))
						else:
							sonidoReturn = (STIMULUSTYPESOUND,TakeTime,EegSyncSignal,sonido,0)
					TakeTime = 0
					EegSyncSignal = 0
			# Load in stimulus chain
			if palabraReturn:
				fraseReturn.append(palabraReturn)
			if imagenReturn:
				fraseReturn.append(imagenReturn)
			if sonidoReturn:
				fraseReturn.append(sonidoReturn)
			if WordByWordReturn:
				fraseReturn.append(WordByWordReturn)
			left = pos[0] + img.get_width()
			WordPos += 1
		if finaldot and showtext:
			if WordByWord:
				left = None
			if IAVP:
				img , pos = self.cargartexto(dotstr,divisor=fontdivisor,Left=left)
			else:
				img , pos = self.cargartexto(dotstr,divisor=fontdivisor,Left=left,totalvertical=totalvertical,verticalpos=verticalpos)
			palabraReturn = (STIMULUSTYPEIMAGE,0,0,img,pos,SN,SST,CS,0,0)
			fraseReturn.append(palabraReturn)
		FullFraseReturn = (OriginalPhrase,good,fraseReturn,correct,ErrorType,NoSaveResult,WaitResponse,NoLoop,ExtraData)
		debug('makephrase: Stimulus Chain: '+str(FullFraseReturn[2]))
		return FullFraseReturn
	
	def show1phrase(self, phrase, hitkey=None):
		"""Show a phrase maked with makephrase.  And take response.
		
		Parameters:
		
		phrases: Phrases maked with makephrase as list of tuples.
		hitkey: Correct answer key as integer.  Is the position of the hey in intento.teclas
		
		Example:
		
		intento.showphrases([phrase1,phrase2], hitkey=1).
		
		Returns 0 if incorrect, 1 if correct."""
		debug('show1phrase: '+phrase[0])
		if self.Result and (not quickrandomresponse):
			ThisTrialFeedback = self.feedback
		else:
			ThisTrialFeedback = 0
		if not self.Result or phrase[5]: # Not Save Result
			IncrementNumero = self.IncrementNumero
			self.IncrementNumero = 0
		resultado = 0
		if phrase[6]: #WaitResponse
			RealTimeLimitTime = self.tiempolimite
			self.tiempolimite = 0
		selectedkey, tiempo, TiempoLimite = self.show(phrase[2])
		if phrase[6]: #WaitResponse
			self.tiempolimite = RealTimeLimitTime
		teclaelegida = 0
		PosTecla = 1
		for Tecla in self.teclas:
			if selectedkey in Tecla:
				teclaelegida = PosTecla
			PosTecla += 1
		if not (hitkey is None):
			if phrase[1]:
				if teclaelegida==hitkey:
					resultado = 1
			else:
				if teclaelegida and teclaelegida!=hitkey:
					resultado = 1
			if (teclaelegida==0) and self.NoAnswerNoFeedback:
				ThisTrialFeedback = 0
			if ThisTrialFeedback:
				if self.PhraseVerboseFeedBack:
					if self.NoAnswerFeedBack:
						self.PhraseFeedBack(resultado,phrase,AnswerKey=teclaelegida)
					else:
						self.PhraseFeedBack(resultado,phrase)
				else:
					if self.NoAnswerFeedBack:
						self.FeedBack(resultado,AnswerKey=teclaelegida)
					else:
						self.FeedBack(resultado)
		if resultado and self.SavePhraseErrorTypeAsResult:
			resultado = phrase[4]
		elif resultado and self.SavePhraseExtraDataKeyAsResult:
			resultado = phrase[8][self.SavePhraseExtraDataKeyAsResult]
		# Saving the result
		if self.Result and not phrase[5]: # Not Save Result
			StimulusNumber=1
			if StimulusNumber > self.StimulusNumber:
				self.StimulusNumber = StimulusNumber
			if phrase[3]:
				StimulusName = [phrase[0]+' = '+phrase[3][0]]
			else:
				StimulusName = [phrase[0]]
			StimulusName.append(phrase[4])
			self.SaveResult(resultado,tiempo,TiempoLimite,teclaelegida,StimulusName)
		else:
			self.IncrementNumero = IncrementNumero
		return resultado

	def PhraseFeedBack(self,resultado,phrase,AnswerKey=None,NoAnswerFeedBack=None):
		"""Show Feedback for Phrases.
		
		Parameters:
		resultado: 0 incorrect, 1 correct.
		phrase: 1 phrase maked with makephrase.
		AnswerKey: Keypressed, if 0, no key pressed, if None, ignore. (None)
				   If NoAnswerFeedBack or self.NoAnswerFeedBack is defined
				   as 1 then if no key is pressed, show specific message.
		NoAnswerFeedBack: Use self.NoAnswerFeedBack instead.  See this below.
		
		Class Properties:
		self.NoAnswerFeedBack: If 1 show specific message for no answer trial.
		self.PhraseMessageNoAnswer: Message if no answer (See above).
		self.PhraseMessageGood    : Message if correct answer.
		self.PhraseMessageError   : Message if wrong answer.
		self.PhraseMessageWrong   : Showed when phrase is wrong.
		self.PhraseMessageRight   : Showed when phrase is right.
		
		Returns nothing.
		"""
		debug('PhraseFeedBack')
		if NoAnswerFeedBack is None:
			NoAnswerFeedBack = self.NoAnswerFeedBack
		# Set Message & Sound
		if NoAnswerFeedBack and not AnswerKey is None and not AnswerKey:
			if self.NoAnswer.sonido:
				feedbacksonido=self.NoAnswer.sonido
			Linea1 = self.PhraseMessageNoAnswer
		else:
			if resultado:
				if self.bien.sonido:
					self.bien.sonido.play()
				Linea1 = self.PhraseMessageGood
			else:
				if self.mal.sonido:
					self.mal.sonido.play()
				Linea1 = self.PhraseMessageError
		if phrase[1]:
			Linea2 = self.PhraseMessageRight
		else:
			Linea2 = self.PhraseMessageWrong
		self.texto(["","","","",Linea1,Linea2],divisor=15,esperarevento=0)
		RealTimeLimitTime = self.tiempolimite
		self.tiempolimite = self.FeedBackShowTime
		CleanScreenBeforeStimulus = self.CleanScreenBeforeStimulus
		self.CleanScreenBeforeStimulus = 0
		espera = self.espera
		self.espera = 0
		IncrementNumero = self.IncrementNumero
		self.IncrementNumero = 0
		# Show the same phrase if it is correct, and "correct" parameter is false.
		if phrase[1] and not self.show(phrase[3][2]):
			self.show(phrase[2])
		else:
			self.show(phrase[3][2])
		self.IncrementNumero = IncrementNumero
		self.espera = espera
		self.CleanScreenBeforeStimulus = CleanScreenBeforeStimulus
		self.tiempolimite = RealTimeLimitTime
	
	def showphrases(self, phrases, hitkey=None,repeat=0,repeatdelay=None):
		"""Show a phrase maked with makephrase.  And take response.
		
		Parameters:
		
		phrases: Phrases maked with makephrase as list.
		hitkey: Correct answer key as integer.  Is the position of the hey in intento.teclas
		
		Example:
		
		intento.showphrases([phrase1,phrase2], hitkey=1).
		
		Returns nothing."""
		debug('showphrases')
		for frase in phrases:
			for loop in range(1+repeat):
				iniciotomatiempo = pygame.time.get_ticks()
				if loop and (not frase[7]): # NoLoop
					# Repeated Delay Trial
					debug('showphrases: Repeated Delay Trial')
					if not (repeatdelay is None):
						espera = self.espera
						self.espera = repeatdelay
					self.show1phrase(frase, hitkey)
					if not (repeatdelay is None):
						self.espera = espera
				elif not loop:
					# Normal Trial
					debug('showphrases: Normal Delay Trial')
					self.show1phrase(frase, hitkey)
				debug('showphrases: Tiempo Transcurrido: '+str(pygame.time.get_ticks()-iniciotomatiempo))
				
	def setkeys(self, teclas):
		"""Set response keys.
		
		Parameters:
		
		teclas: Response keys.
		
		Example:
		
		intento.setkeys([[K_LSHIFT],[K_RSHIFT]])
		
		Returns: None """
		debug('setkeys')
		self.teclas = teclas
		self.keys=[]
		for grupo in self.teclas:
			for tecla in grupo:
				self.keys.append(tecla)

	def generar(self,Muestras,Emparejar,Relaciones=[],GenerateNoValidChoice=None,
			 GenerateMultipleValidChoices=None):
		"""Make all posible convinations of Sample and Matching stimulus.
		Use it with intento.aleatorio.
		
		Parameters:
		Muestras: All Sample stimulus as list.
		Emparejar: All Matching stimulus as list
		Relaciones: All Relations between stimulus as list (optional).
		GenerateNoValidChoice: Default 0, except only one selection key, then 1.
		GenerateMultipleValidChoices: Default 0.
		
		Returns a list of all convinations used by intento.aleatorio."""
		debug('generar')
		debug('Muestras: ' + str(Muestras))
		debug('Emparejar: ' + str(Emparejar))
		debug('Relaciones: ' + str(Relaciones))
		if len(self.teclas)==1:
			GenerateNoValidChoice=1
		if GenerateNoValidChoice is None:
			GenerateNoValidChoice = self.GenerarGenerateNoValidChoice
		if GenerateMultipleValidChoices is None:
			GenerateMultipleValidChoices = self.GenerarGenerateMultipleValidChoices
		self.texto([u"Creando combinaciones de estímulos","Por favor, espere."],esperarevento=0)
		resultado=[]
		combinaciones=combinar(Emparejar,len(self.teclas))
		if not Relaciones:
			# Without relations
			for muestra in Muestras:
				for estimulos in combinaciones:
					OK = 0
					for cadauno in estimulos:
						# Debo verificar que solo haya una respuesta correcta.
						# I must check if have only one correct answer.
						if cadauno[0] in self.clasesfacil[muestra[0]]:
							OK += 1
					if ((OK==1) or ((OK==0) and GenerateNoValidChoice)
						or ((OK>1) and GenerateMultipleValidChoices)):
						resultado.append([muestra,estimulos])
		else:
			# With relations
			for muestra in Muestras:
				for relacion in Relaciones:
					for estimulos in combinaciones:
						OK = 0
						for cadauno in estimulos:
							# Debo verificar que solo haya una respuesta correcta.
							# I must check if have only one correct answer.
							if relacion[0]+cadauno[0] in self.clasesfacil[muestra[0]]:
								OK += 1
						if OK==1:
							resultado.append([muestra,relacion,estimulos])
		if not resultado:
			resultado = None
		debug('generar: resultado: ' + str(resultado))
		return resultado

	def aleatorio(self,Estimulos,PresentarTodos=1,MinTrials=-1,MaxTrials=-1,
			MinAciertos=-1,MaxAciertos=-1,MMAciertosConsecutivos=-1,
			MinAciertosConsecutivos=-1,MaxAciertosConsecutivos=-1,MinPorcentajeAciertos=0,
			TrialsDeAciertosConsecutivos=0):
		"""Show a list of Samples and Stimulus maked with intento.generar().
		This list 'Estimulos' is disordered with random.shuffle(Estimulos).
		
		Correct answers are determined by intento.clases().
		
		Answer keys are determined by intento.setkeys().
		
		Parameters:
		Estimulos: Stimulus set maked with intento.generar().
		PresentarTodos: Show complete list of stimulus.
		MinTrials: Minimal count of Trials.
		MaxTrials: Maximal count of Trials.
		MinAciertos: Minimal count of correct answers.
		MaxAciertos: Maximal count of correct answers.
		MMAciertosConsecutivos: Maximal and Minimal count of correct answers consecutively.
		MinAciertosConsecutivos: Minimal count of correct answers consecutively.
		MaxAciertosConsecutivos: Maximal count of correct answers consecutively."""
		debug('aleatorio')
		if shortflag:
			MinTrials=-1; MaxTrials=-1; MinAciertos=-1;	MaxAciertos=-1; AciertosConsecutivos=-1
			MinAciertosConsecutivos=-1;	MaxAciertosConsecutivos=-1
		if MMAciertosConsecutivos>0:
			MinAciertosConsecutivos=MaxAciertosConsecutivos=MMAciertosConsecutivos
		if MinTrials==-1 and MinAciertos==-1 and MinAciertosConsecutivos==-1:
			MinTrials=len(Estimulos)
		if MaxTrials==-1 and MaxAciertos==-1 and MaxAciertosConsecutivos==-1:
			MaxTrials=len(Estimulos)
		if MaxTrials<=MinTrials:
			MaxTrials=MinTrials				
		if TrialsDeAciertosConsecutivos:
			MaxYerrosAciertosConsecutivos = TrialsDeAciertosConsecutivos - MinAciertosConsecutivos
		else:
			MaxYerrosAciertosConsecutivos = 0
		Trial = 0
		UltimosTrials = []
		Aciertos = 0
		AciertosConsecutivos = 0
		YerrosAciertosConsecutivos = 0
		AlcanzoMinAciertosConsecutivos = 0
		AlcanzoMinPorcentajeAciertos = 0
		seguir = 1
		while seguir:
			debug('aleatorio: random.shuffle(Estimulos)')
			random.shuffle(Estimulos)
			for CadaEstimulo in Estimulos:
				if self.UsePresentarClic:
					if len(CadaEstimulo)==2:
						resultado=self.presentarClic([CadaEstimulo[0]],CadaEstimulo[1])
					elif len(CadaEstimulo)==3:
						resultado=self.presentarClic([CadaEstimulo[0]],CadaEstimulo[2],[CadaEstimulo[1]])
				else:
					if len(CadaEstimulo)==2:
						resultado=self.presentar([CadaEstimulo[0]],CadaEstimulo[1])
					elif len(CadaEstimulo)==3:
						resultado=self.presentar([CadaEstimulo[0]],CadaEstimulo[2],[CadaEstimulo[1]])
				Aciertos += resultado
				if TrialsDeAciertosConsecutivos:
					while len(UltimosTrials)>=TrialsDeAciertosConsecutivos:
						trash = UltimosTrials.pop(0)
					UltimosTrials.append(resultado)
				if resultado:
					AciertosConsecutivos=AciertosConsecutivos+resultado
					if MinAciertosConsecutivos>-1 and AciertosConsecutivos>=MinAciertosConsecutivos:
						AlcanzoMinAciertosConsecutivos = 1
				else:
					if TrialsDeAciertosConsecutivos:
						for TrialInMemory in UltimosTrials:
							YerrosAciertosConsecutivos += int(not TrialInMemory)
						if YerrosAciertosConsecutivos>=MaxYerrosEnAciertosConsecutivos:
							AciertosConsecutivos = 0
					else:
						AciertosConsecutivos = 0
				Trial += 1
				if MinPorcentajeAciertos:
					PorcentajeAciertos = Aciertos * 100.00 / Trial
					AlcanzoMinPorcentajeAciertos = PorcentajeAciertos >= MinPorcentajeAciertos
				if ((MaxTrials>0 and MaxTrials<=Trial and Trial>=MinTrials and Trial>=(len(Estimulos)*PresentarTodos)) or
				(MaxAciertos>0 and MaxAciertos<=Aciertos and Aciertos>=MinAciertos and Trial>=MinTrials and Trial>=(len(Estimulos)*PresentarTodos)) or
				(MaxAciertosConsecutivos>0 and MaxAciertosConsecutivos<=Aciertos and Trial>=MinTrials and Trial>=(len(Estimulos)*PresentarTodos)) or
				(MinAciertosConsecutivos>0 and AciertosConsecutivos>=MinAciertosConsecutivos and Trial>=MinTrials and Trial>=(len(Estimulos)*PresentarTodos)) or
				(MinPorcentajeAciertos>0 and AlcanzoMinPorcentajeAciertos and Trial>=MinTrials and Trial>=(len(Estimulos)*PresentarTodos))):
					seguir=0
					break
				if self.TrialSep and seguir:
					self.TrialSeparator()
		return (AlcanzoMinAciertosConsecutivos or AlcanzoMinPorcentajeAciertos)

	
	def TrialSeparator(self,Separator=None):
		"""
		This need documentation.
		"""
		if Separator is None:
			Separator = self.TrialSep
		if self.TrialSep:
			# def texto(self,Texto,agrandar=0,divisor=0,tamanio=0,colortext=0,
			# esperarevento=1,escsale=0, CleanScreen=1,AnswerKeys=[K_SPACE]):
			if isinstance(Separator,dict):
				H = {'Texto': '', 'agrandar': 0,'divisor': 0,'tamanio': 0,'colortext': 0,
					'esperarevento': 1,'escsale': 0, 'CleanScreen': 1,'AnswerKeys': [K_SPACE]}
				for i in H:
					H[i] = Separator[i]
				self.texto(H['Texto'],H['agrandar'],H['divisor'],H['tamanio'],
					H['colortext'],H['esperarevento'],H['escsale'],
					H['CleanScreen'],H['AnswerKeys'])
			else:
				PresentarSaveResults = self.PresentarSaveResultsNow
				self.PresentarSaveResultsNow = 0
				LimitTime = self.tiempolimite
				self.tiempolimite = 0
				FeedBack = self.feedback
				self.feedback = 0
				Wait = self.espera
				self.espera = 0
				Result = self.Result
				self.Result = 0
				IncrementarNumero = self.IncrementNumero
				self.IncrementNumero = 0
				CheckNodalDistance = self.checknodaldistance
				self.checknodaldistance = 0
				self.FullScreen(Separator[0],Separator[1])
				self.checknodaldistance = CheckNodalDistance
				self.IncrementNumero = IncrementarNumero
				self.espera = Wait
				self.Result = Result
				self.feedback = FeedBack
				self.tiempolimite = LimitTime
				self.PresentarSaveResultsNow = PresentarSaveResults
		return

	def presentarClic(self,muestra,emparejar,Relacion=[]):
		"""
		This need Documentation.
		"""
		debug('presentarClic')
		PresentarSaveResults = self.PresentarSaveResultsNow
		self.PresentarSaveResultsNow = 0
		LimitTime = self.tiempolimite
		self.tiempolimite = 0
		FeedBack = self.feedback
		self.feedback = 0
		Result = self.Result
		self.Result = 0
		IncrementarNumero = self.IncrementNumero
		self.IncrementNumero = 0
		CheckNodalDistance = self.checknodaldistance
		self.checknodaldistance = 0
		# Sample
		CleanScreenAfterResponse = self.CleanScreenAfterResponse
		self.CleanScreenAfterResponse = 0
		# Don't wait
		if isinstance(self.retraso,list):
			if not self.retrasoList:
				if self.retrasoRandom:
					random.shuffle(self.retraso)
				self.retrasoList = copy.copy(self.retraso)
			RetrasoMuestra = self.retrasoList.pop()
		else:
			RetrasoMuestra = copy.copy(self.retraso)
		tiempomuestra = self.tiempomuestra
		retraso = self.retraso
		self.tiempomuestra = 0
		self.retraso = 0
		SinPersistencia = self.sinpersistencia
		self.sinpersistencia = 0
		# Show Sample
		self.presentar(muestra,[])
		# Don't clear screen and not wait between stimulus
		CleanScreenBeforeStimulus = self.CleanScreenBeforeStimulus
		self.CleanScreenBeforeStimulus = 0
		espera = self.espera
		self.espera = 0			
		if SinPersistencia:
			cleanscreen()
		pygame.time.delay(RetrasoMuestra)
		# Relation
		if Relacion:
			self.presentar([],[],relacion=Relacion)
		self.checknodaldistance = CheckNodalDistance
		self.IncrementNumero = IncrementarNumero
		self.Result = Result
		self.feedback = FeedBack
		self.tiempolimite = LimitTime
		self.PresentarSaveResultsNow = PresentarSaveResults
		self.CleanScreenAfterResponse = CleanScreenAfterResponse
		# Match
		self.sinpersistencia = SinPersistencia
		resultado = self.presentar(muestra,emparejar,relacion=Relacion)
		self.CleanScreenBeforeStimulus = CleanScreenBeforeStimulus
		self.espera = espera
		self.tiempomuestra = tiempomuestra
		self.retraso = retraso
		return resultado
		
				
	def nBack(self,Serie,Nback=None):
		"""Display an image serie centered in screen, takes key pressed and time
		and Nback response.
		Parameters:
		Serie: An image Serie of images loaded with self.cargarestimulo
				with NBack=1 parameter.
		Nback: Numbers of stimulus to remember (optional).
		
		Example:
		nBack([A,B,A],2)
		This show letter A first, then B, and again A
		In first 2 shows correct answer is not response.
		In third show correct answer is press a key in self.teclas"""
		debug('nBack')
		if (Nback is None) and (not (self.nBackNumber is None)):
			Nback = self.nBackNumber
		elif self.nBackNumber is None:
			debugging = 1
			debug('*** Error: nBack function without Nback parameter or self.nBackNumber defined'+sheetname)
			mensaje = ["nBack function without Nback","parameter or self.nBackNumber defined","",
			"Para salir presione:","La barra espaciadora"]
			self.texto(mensaje)
			raise "nBack function without Nback parameter or self.nBackNumber defined"
		posicion=0
		for estimulo in Serie:
			responder=0
			deberecordar=posicion-Nback
			if deberecordar>=0:
				if Serie[deberecordar]==estimulo:
					responder=1
			if len(self.teclas)>1 and self.nBackAlwaysResponse:
				responder += 1
			self.presentar([estimulo],[],teclaacierto=responder)
			posicion+=1

	def	nBackSpatial(self,Serie,Nback=None):
		"""Display an image serie at some position, takes key pressed and time
		and Nback response.
		Parameters:
		Serie: An image Serie of images loaded with self.cargarestimulo
				with NBackSpatial=1 parameter and their position.
		Nback: Numbers of stimulus to remember.
		
		Example:
		nBackSpatial([[A,1],[A,2],[A,1]],2)
		This show the image A first in position 1, then in position 2, and again in 1
		In first 2 shows correct answer is not response.
		In third show correct answer is press a key in self.teclas"""
		debug('nBackSpatial')
		if (Nback is None) and (not (self.nBackNumber is None)):
			Nback = self.nBackNumber
		elif self.nBackNumber is None:
			mensaje = ["nBack function without Nback","parameter or self.nBackNumber defined","",
			"Para salir presione:","La barra espaciadora"]
			self.texto(mensaje)
			raise "nBack function without Nback parameter or self.nBackNumber defined"
		posicion=0
		for estimulo in Serie:
			responder=0
			deberecordar=posicion-Nback
			if deberecordar>=0:
				if Serie[deberecordar]==estimulo:
					responder=1
			if len(self.teclas)>1 and self.nBackAlwaysResponse:
				responder += 1
			self.presentar([estimulo[0]],[],teclaacierto=responder,LugarEstimulo=estimulo[1]-1)
			posicion+=1

	def	PrimeTask(self,Serie):
		"""Display two stimuli(text or image) in screen centered.
		
		First a sample.
		
		Second a target.
		
		If sample and target are in the same class, answer must be key 2, else 1.
		
		Parameters:
		Serie: stimulus serie maked with self.generar
		
		Returns nothing."""
		debug('PrimeTask')
		for estimulo in Serie:
			responder=int([estimulo[1][0]][0][0] in self.clasesfacil[[estimulo[0]][0][0]])+1
			self.presentar([estimulo[0]],[estimulo[1][0]],teclaacierto=responder, LugarEstimulo=0,
				  IncPosicionEstimulo=0,StartPosicionEstimulo=2,SaveStimulusPosition=0)

	def	DotMixTask(self,Serie):
		"""Dot Mixed Task Experiment.
		
		Serie: Stimulus Serie.
		
		Example:
		
		miintento.setkeys([[K_LSHIFT],[K_RSHIFT]])
		
		opposite = miintento.cargarestimulo('opposite.jpg',Alias='!=',DotMixedTask=1)
		same = miintento.cargarestimulo('same.jpg',Alias='==',DotMixedTask=1)
		
		# Opuesto Derecha    -  Opposite Right
		OD = [opuesto,2]
		
		# Opuesto Izquierda  -  Opposite Left
		OI = [opuesto,1]
		
		# Igual Derecha      -  Same Right
		ID = [igual,2]
		
		# Igual Izquierda    -  Same Left
		II = [igual,1]
		
		Serie1=[ID, II]
		Serie2=[OD, OI]
		
		miintento.DotMixTask(Serie1)
		"""
		debug('DotMixTask')
		for estimulo in Serie:
			if estimulo[0][0] == '==':
				responder = estimulo[1]
			elif estimulo[0][0] == '!=':
				responder = estimulo[1] + 1
				if responder > 2:
					responder = 1
			else:
				mensaje = ["DotMixTask error:","equal or not equal,","other alias given.","",
				"Para salir presione:","La barra espaciadora"]
				self.texto(mensaje)
				raise "DotMixTask error: equal or not equal, other alias given."
			self.presentar([estimulo[0]],[],teclaacierto=responder,LugarEstimulo=estimulo[1]-1)

	def	Stroop(self,Serie,Target=None):
		"""
		This need documentation.
		"""
		debug('Stroop')
		if (Target is None) and (not (self.AliasTarget is None)):
			Target = self.AliasTarget
		if self.AliasTarget is None:
			mensaje = ["Stroop function without Target","parameter or self.AliasTarget defined","",
			"Para salir presione:","La barra espaciadora"]
			self.texto(mensaje)
			raise "Stroop function without Target parameter or self.AliasTarget defined"
		for estimulo in Serie:
			AliasList = estimulo[0].split(',')
			responder = self.keyalias.index(AliasList[Target])+1
			self.presentar([estimulo],[],teclaacierto=responder)

	def AGL(self, Serie):
		"""
		This need documentation.
		"""
		count = 1
		self.PresentarSaveResultsNow = 0
		self.haymuestra = 1
		for estimulo in Serie:
			if not self.AGLExperiment:
				self.AGLExperiment = 1
			if self.AGLAskCertainty:
				if not self.AGLWithCertainty:
					self.AGLWithCertainty = 1
				self.CleanScreenAfterResponse = 0
			if self.AGLAskCertainty or self.AGLConfirmStimulus:
				FeedBack = self.feedback
				self.feedback = 0
			if self.AGLConfirmStimulus:
				UserKeys = self.teclas
				self.setkeys([[]])
			if self.PresentarFullResult:
				PrevTime = copy.copy(self.PresentarFullResult[1][1][0])
			else:
				PrevTime = 0
			self.PresentarFullResult = []
			self.presentar([],self.AGLTargets, teclaacierto=estimulo[8]['Key'],
				StartPosicionEstimulo=1,
				ExternalChains=[[estimulo[2],self.AGLType,self.AGLPos]]+self.AGLExtraStimulusChain)
			## self.SaveResult(resultado,tiempo,TiempoLimite,teclaelegida,linearesultado)
			PR = copy.copy(self.PresentarFullResult)
			PR[4].insert(1,estimulo[0])
			debug('PresentarResult: ' + str(PR))
			if self.AGLAskCertainty:
				LimitTime = self.tiempolimite
				self.tiempolimite = 0
				Wait = self.espera
				self.espera = 0
				Result = self.Result
				self.Result = 0
				self.IncrementNumero = 0
				self.CleanScreenBeforeStimulus = 0
				self.CleanScreenAfterResponse = 1
				UserKeys = self.teclas
				self.setkeys(self.AGLCertaintyKeys)
				debug('self.teclas: ' + str(self.teclas))
				self.PresentarFullResult = []
				if PR[3]:
					self.presentar([],self.AGLCertaintyTargets,StartPosicionEstimulo=1)
				else:
					self.PresentarFullResult = [0,[[],[0]],0,0,['','','','']]
				self.setkeys(UserKeys)
				PR2 = copy.copy(self.PresentarFullResult)
				self.IncrementNumero = 1
				self.CleanScreenBeforeStimulus = 1
				self.tiempolimite = LimitTime
				self.espera = Wait
				self.Result = Result
				self.feedback = FeedBack
				debug('PR[4]: ' + str(PR[4]))
				debug('PR2: ' + str(PR2))
				self.StimulusNumber = len(UserKeys)
				if self.AGLCertaintyKeysAlias:
					Certainity = self.AGLCertaintyKeysAlias[PR2[3]-1]
				else:
					Certainity = PR2[3]
				## self.SaveResult(resultado,tiempo,TiempoLimite,teclaelegida,linearesultado)
				linearesultado = PR[4]+[estimulo[4],Certainity,PR2[1][1][0]]
				if PrevTime and self.IncludePresentarFullResultTime:
					linearesultado.append(PrevTime)
				self.SaveResult(PR[0],PR[1],PR[2],PR[3],linearesultado)
			else:
				if not self.AGLConfirmStimulus:
					linearesultado = PR[4]+[estimulo[4]]
					if PrevTime and self.IncludePresentarFullResultTime:
						linearesultado.append(PrevTime)
					self.SaveResult(PR[0],PR[1],PR[2],PR[3],linearesultado)
			if self.AGLConfirmStimulus:
				self.PreguntarTimeLimit = self.AGLConfirmStimulusTimeLimit
				if self.AGLConfirmStimulusDefaultOptions:
					self.PreguntarForceUpperCase = 1
					self.PreguntarIgnoreReturn = 1
					self.PreguntarIgnoreBackSpace = 1
					self.PreguntarCheckValidImmediately = 1
					self.PreguntarCenterInputToValidity = 1
				if self.AGLConfirmStimulusDefaultColors:
					self.PreguntarPromptFontColor = white
					self.PreguntarInputAreaColor = black
					self.PreguntarInputTextColor = white
					self.PreguntarBackColor = black
					self.PreguntarInputBoxInputColor = black
				EchoWord = self.Preguntar(self.AGLConfirmStimulusPrompt,estimulo[0],self.AGLConfirmStimulusFontDivisor)
				EchoOutCome = int(estimulo[0].upper()==EchoWord.upper())
				debug('EchoOutCome: '+str(EchoOutCome))
				self.feedback = FeedBack
				if self.feedback:
					FeedBackStimuli = copy.copy(estimulo)
					## if not FeedBackStimuli[3]:
						## FeedBackStimuli[1] = 1
					self.PhraseFeedBack(EchoOutCome,FeedBackStimuli)
				self.SaveResult(EchoOutCome,[[],[self.PreguntarTime]],
					self.PreguntarTimeLimitReached,EchoWord,PR[4]+[estimulo[4]])
				self.setkeys(UserKeys)
			if self.AGLsep and len(Serie)>count:
				self.TrialSeparator(self.AGLsep)
			count+=1
		self.PresentarSaveResultsNow = 1

	def	FullScreen(self,Serie,Target=[],UsedAsSeparator=None):
		"""Display an image serie at full screen, takes key pressed and time.
		Parameters:
		Serie: An image Serie of images loaded with self.cargarestimulo
				with FullScreen=1 parameter
		Target: Clic Targets."""
		debug('FullScreen')
		if UsedAsSeparator is None:
			UsedAsSeparator = self.FullScreenUsedAsSeparator
		if UsedAsSeparator:
			PresentarSaveResults = self.PresentarSaveResultsNow
			Retraso = self.retraso
			TiempoMuestra = self.tiempomuestra
			CheckNodalDistance = self.checknodaldistance
			IncrementarNumero = self.IncrementNumero
			SinPersistencia = self.sinpersistencia
			self.PresentarSaveResultsNow = 0
			self.retraso = 0
			self.checknodaldistance = 0
			self.tiempomuestra = 0
			self.IncrementNumero = 0
			self.sinpersistencia = 0
		SelfResult = self.Result
		self.Result = 0
		for estimulo in Serie:
			self.PresentarFullResult = []
			self.presentar([estimulo],Target,IncPosicionEstimulo=0)
		self.Result = SelfResult
		if UsedAsSeparator:		
			self.PresentarSaveResultsNow = PresentarSaveResults
			self.retraso = Retraso
			self.tiempomuestra = TiempoMuestra
			self.checknodaldistance = CheckNodalDistance
			self.IncrementNumero = IncrementarNumero
			self.sinpersistencia = SinPersistencia
		
	def	SlideShow(self,Serie,Range,istarget=0):
		"""Display an slide serie at full screen.
		Parameters:
		Serie: An slide Serie of images loaded with self.cargarestimulo
				with FullScreen=1 parameter"""
		debug('SlideShow')
		SelfResult = self.Result
		self.Result = 0
		TakeTime = 0
		EegSyncSignal = 0
		SN = 0
		SST = 0
		CS = 0
		Delay = 0
		while self.numero>=Range[0] and self.numero<=Range[1]:
			self.ShowExample = 1
			estimulo = Serie[self.numero]
			slide = [[STIMULUSTYPEIMAGE, TakeTime, EegSyncSignal, estimulo[2], estimulo[3][0],SN,SST,CS,Delay,istarget]]
			selectedkey, tiempo, TiempoLimite = self.show(slide)
			if selectedkey in self.teclas[0] and self.numero>=2:
				self.numero -= 2
			elif selectedkey in self.teclas[0]:
				self.numero -= 1
			elif selectedkey in self.teclas[2]:
				self.ShowExample = 0
		self.Result = SelfResult

	def guardar(self):
		"""Save results in a file. No parameters
		
		self.SaveAsFileFormat: "csv" or "ods". Default is "csv".
		
		Results are saved in:
		Linux/Unix/Mac: /home/user/Mis resultados del experimento/
		Windows: Mis documentos\\Mis resultados del experimento
		
		If experiment is portable, use portable.ini directories."""
		debug('guardar')
		FinalTime = time.time()
		cabeceras=self.makeheaders()
		if self.resultados:
			debug('guardar: Exists Experiment Results')
			if self.resultados[0]!=cabeceras:
				debug('guardar: Add Headers')
				self.resultados.insert(0,cabeceras)
				# Datos Adicionales
				self.resultados.insert(0,['SF:',str(shortflag)])
				self.resultados.insert(0,['RR:',str(randomresponse)])
				self.resultados.insert(0,['QR:',str(quickrandomresponse)])
				self.resultados.insert(0,['SR:',str(SoundRecorder)])
				self.resultados.insert(0,['BB:',str(blackback)])
				self.resultados.insert(0,['XL:',str(excludelist)])
				self.resultados.insert(0,['SC:',str(GoDownBad)])
				self.resultados.insert(0,['BD:',str(buildnumber)])
				self.resultados.insert(0,['DM:',str(debugging)])
				self.resultados.insert(0,['ES:',str(int(FinalTime))])
				self.resultados.insert(0,['DS:',str(int(StartTime))])
				self.resultados.insert(0,['FS:',str(self.fallosonido)])
				self.resultados.insert(0,['OS:',SistemaOperativo])
				self.resultados.insert(0,['US:',str(usersize)[1:-1].replace(', ','x')])
				# Tiempo Legible
				strFinalTime=time.strftime("%x %X UTC", time.gmtime(FinalTime))
				strStartTime=time.strftime("%x %X UTC", time.gmtime(StartTime))
				self.resultados.insert(0,['TF:',strFinalTime])
				self.resultados.insert(0,['TI:',strStartTime])
				# Researcher and unique ID
				self.resultados.insert(0,['RS:',RESEARCHER])
				self.resultados.insert(0,['CD:',UCID])
				self.resultados.insert(0,['ID:',UUID])
				# Firma digital
				strResultados = str(self.resultados).replace(", u'",', ').replace("[u'","[").replace("', ",", ").replace(", '",", ").replace("']", "]").replace("['","[")
				## print str(self.resultados)
				## print strResultados
				## sys.exit()
				SHA1=hashlib.sha1(strResultados).hexdigest()
				self.resultados.insert(0,['OK:',SHA1])
			CountSaveTrials = 0
			SaveNotConfirmed = 1
			while SaveNotConfirmed and CountSaveTrials<100:
				debug('guardar: Save Confirmation Loop')
				CountSaveTrials += 1
				if self.SaveAsFileFormat=="ods":
					debug('guardar: self.SaveAsFileFormat=="ods"')
					doc = ooolib.Calc()
					for row in range(len(self.resultados)):
						for col in range(len(self.resultados[row])):
							if self.resultados[row][col].isdigit():
								doc.set_cell_value(col+1, row+1, "float", int(self.resultados[row][col]))
							else:
								doc.set_cell_value(col+1, row+1, "string", self.resultados[row][col])
					doc.save(directorio+os.sep+NombreArchivoDatosODS)
					NombreArchivoDatos = NombreArchivoDatosODS
				else:
					debug('guardar: self.SaveAsFileFormat!="ods"')
					FileHandler = open(directorio+os.sep+NombreArchivoDatosTSV, "wb")
					writer = UnicodeWriter(FileHandler,dialect='excel-tab')
					writer.writerows(self.resultados)
					FileHandler.close()
					NombreArchivoDatos = NombreArchivoDatosTSV
				SaveNotConfirmed = not self.ConfirmSaved(directorio+os.sep+NombreArchivoDatos)
			debug('*** Results Saved: '+time.strftime('%x %X UTC', time.gmtime(time.time())))
			mensaje=directorio.split(os.sep)
			if len(mensaje)>1:
				mensaje[0]=mensaje[0]+os.sep+mensaje[1]
				mensaje.remove(mensaje[1])
			for i in range(len(mensaje)):
				mensaje[i]=mensaje[i]+os.sep
			mensaje.insert(0,"Sus resultados fueron guardados en:")
			mensaje.append("Con el nombre:")
			mensaje.append(NombreArchivoDatos)
			mensaje.append("Para terminar presione")
			mensaje.append("La Barra Espaciadora")
			self.texto(mensaje,escsale=1)
	
	def ConfirmSaved(self, Archivo):
		"""
		Used internally, don't use this function.
		
		Usado internamente, no use esta función.
		"""
		A=[]
		Result = 0
		if os.access(Archivo,os.F_OK):
			if self.SaveAsFileFormat=="ods":
				# Horrible Solution
				return 1
				# Importar ODS
				doc = ooolib.Calc()
				doc.load(Archivo)
				cols, rows  = doc.get_sheet_dimensions()
				for row in range(1,rows+1):
					columns = []
					for col in range(1,cols+1):
						if doc.get_cell_value(col,row) is None:
							tipocelda, valorcelda = ('string',u'')
						else:
							tipocelda, valorcelda = doc.get_cell_value(col,row)
						valorcelda = valorcelda.replace('&amp;', '&')
						valorcelda = valorcelda.replace('&apos;', "'")
						valorcelda = valorcelda.replace('&quot;', '"')
						valorcelda = valorcelda.replace('&lt;', '<')
						valorcelda = valorcelda.replace('&gt;', '>')
						valorcelda = valorcelda.replace('<text:tab-stop/>', '\t')
						valorcelda = valorcelda.replace('<text:line-break/>', '\n')
						if isinstance(valorcelda,basestring):
							columns.append(valorcelda)
						else:
							columns.append(str(valorcelda))
					A.append(columns)
			else:
				FileHandler = open(Archivo, 'rb')
				Areader = csv.reader(FileHandler,dialect='excel-tab')
				for row in Areader:
					if row[0] in ControlHeaders:
						row = [row[0], row[1]]
					else:
						for cell in range(len(row)):
							row[cell] = row[cell].decode('utf8','ignore')
					A.append(row)
				FileHandler.close()
			Chequeo = A[0][1]
			A.remove(A[0])
			strA = str(A).replace(", u'",', ').replace("[u'","[").replace("', ",", ").replace(", '",", ").replace("']", "]").replace("['","[")
			SHA1=hashlib.sha1(strA).hexdigest()
			Result = Chequeo==SHA1
			if not Result:
				debug('ConfirmSaved: RemoveFile')
				os.remove(Archivo)
		return Result
		
	def makeheaders(self):
		"""Make headers for result file.  No parameters.
		
		Set your own headers:
		
		self.userheaders = ['my','headers']
		"""
		debug('makeheaders')
		cabeceras=[]
		if grupo:
			cabeceras=['Grupo']
		if Condition:
			cabeceras.append('Condicion')
		cabeceras.append('Sujeto')
		cabeceras.append('Genero')
		cabeceras.append('Edad')
		if self.fase:
			cabeceras.append('Fase')
		if self.bloque:
			cabeceras.append('Bloque')
		cabeceras.append('Trial')
		if self.Result:
			cabeceras.append('Respuesta')
		if self.StimulusTakeTimeMaxCount:
			for numero in range(self.StimulusTakeTimeMaxCount):
				cabeceras.append('TiempoEstimulo'+str(numero+1))
		if self.LastTakeTime:
			if self.StimulusTakeTimeMaxCount==0:
				cabeceras.append('Tiempo')
			elif self.StimulusTakeTimeMaxCount>=1:
				cabeceras.append('Tiempo Final')
		cabeceras=cabeceras+['Limite','Tecla']
		if self.StimulusNumber > 1:
			cabeceras.append('Elegido')
		if self.haymuestra:
			cabeceras.append('Muestra')
		if self.hayrelacion:
			cabeceras.append('Relacion')
		for i in range(self.StimulusNumber):
			cabeceras.append('Estimulo'+str(i+1))
		if self.checknodaldistance:
			cabeceras.append('DisNodal')
		if self.IncludePresentarRetrasoMuestra:
			cabeceras.append('RetrasoMuestra')
		if self.IncludePresentarRetrasoRelacion:
			cabeceras.append('RetrasoRelacion')	
		if self.IncludePresentarFullResultTime:
			if self.IncludePresentarFullResultTime==1:
				cabeceras.append('PrevTime')
			else:
				for i in range(1,self.IncludePresentarFullResultTime+1):
					cabeceras.append('PrevTime'+str(i))
		if self.PhraseErrorType:
			cabeceras.append('ErrorType')
		if self.AGLWithCertainty:
			cabeceras.append('Certainty')
			cabeceras.append('CertaintyTime')
		if self.userheaders:
			cabeceras = cabeceras + self.userheaders
		if SoundRecorder:
			cabeceras.append('SoundFile')
		return cabeceras

	def texto(self,Texto,agrandar=0,divisor=0,tamanio=0,colortext=0,esperarevento=1,escsale=0,
		CleanScreen=1,AnswerKeys=[K_SPACE]):
		"""Show a text in the screen, and by default waits for spacer press.
		Parameters:
		Texto:  Text to display (Required).
		agrandar: increase font size (int).
		divisor: proportinal divisor of screen width (int) for font size.
		tamanio: Font size (int).
		colortext: Text color (RGB).
		esperarevento: Wait for event.  Default: 1 (Yes).
		escsale: Esc key quit. Default: 0 (No)
		"""
		debug('texto')
		if quickrandomresponse:
			esperarevento=0
		if CleanScreen:
			cleanscreen() # Limpiar la pantalla
		Alto=len(Texto)+1
		Ancho=0
		for Linea in Texto:
			if len(Linea)>Ancho:
				Ancho=len(Linea)
		actual=0
		if not divisor:
			divisor=(screen.get_width()/Ancho)+agrandar
		if tamanio:
			tamaniotexto=tamanio
		else:
			tamaniotexto=(screen.get_width()/divisor)+agrandar
		if not colortext:
			colortext=textcolor
		for Linea in Texto:
			actual+=1
			lateral = screen.get_width()/2
			altura=(screen.get_height()/(Alto))*actual
			font = pygame.font.Font(letra, tamaniotexto)
			text = font.render(Linea, 1, (colortext))
			textpos = text.get_rect(centerx=lateral,centery=altura)
			screen.blit(text, textpos)
		actual_screen = screen.copy()
		pygame.display.flip()
		screen.blit(actual_screen,(0,0))
		pygame.event.clear()
		while esperarevento:
			event=pygame.event.wait()
			if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
				if escsale:
					sys.exit()
				else:
					self.salir()
			if event.type == KEYDOWN and (event.key in AnswerKeys):
				esperarevento = 0
				return event.key

	def salir(self,Mensaje=[u"¿Salir? (S/N)"],K_Salir=K_s,K_Seguir=K_n):
		"""Display an exit text to quit.
		Parameters:
		Mensaje: Explanation text. Default "¿Salir? (S/N)"
		K_Salir: Exit key.  Default: K_s
		K_Seguir: Cancel exit key. Default: K_n"""
		debug('salir')
		screen_backup = screen.copy()
		screen.fill(background)
		Alto=len(Mensaje)+1
		Ancho=0
		for Linea in Mensaje:
			if len(Linea)>Ancho:
				Ancho=len(Linea)
		actual=0
		for Linea in Mensaje:
			actual+=1
			lateral = screen.get_width()/2
			altura=(screen.get_height()/(Alto))*actual
			font = pygame.font.Font(letra, (screen.get_width()/Ancho))
			text = font.render(Linea, 1, (textcolor))
			textpos = text.get_rect(centerx=lateral,centery=altura)
			screen.blit(text, textpos)		
		pygame.display.flip()
		pygame.event.clear()
		seguir=1
		while seguir:
			event=pygame.event.wait()
			if event.type == QUIT or (event.type == KEYDOWN and (event.key == K_Salir)):
				if soundrecorderpid:
					stopsoundrecorder()
				if self.resultados:
					global GoDownBad
					GoDownBad = 1
					self.guardar()
				sys.exit()
			if event.type == KEYDOWN and (event.key == K_Seguir):
				seguir = 0
				screen.blit(screen_backup,screen_backup.get_rect())
				pygame.display.flip()

	def cargarestimulo(self,NombreImagen,Alias='',Aplanar=0,NroMuestras=1,NroFilasEstimulos=2,
		NroColumnasEstimulos=None,Texto=None,agrandar=0,divisor=None,tamanio=0,colortext=0,
		backcolortext=0,NBackSpatial=0,NBack=0,FullScreen=0,Relations=None,DotMixedTask=0,
		Folder=None,colorkey=None,convert=0,Sound=None,SoundExtraTime=None,
		SoundFolder=None,SoundFileType=None,AddCentralPosition=None,
		IgnoreRows=[],IgnoreCols=[]):
		""" Los Estimulos deben estar en el subdirectorio Estimulos
		Stimulus must be in subdirectory Estimulos.
		
		Load an image as stimulus or make and stimulus from text.
		
		Parameters:
		NombreImagen: Stimulus image file name, or Text.
		Alias: Alternate name for stimulus.
		Aplanar: join stimulus in a same group, used by NBackSpatial.
		NroMuestras: Number of Sample stimulus.  Normaly only one.
		NroFilasEstimulos: Number of Stimulus rows.
		NroColumnasEstimulus: Number of Stimulus columns, normaly determined by len(intento.teclas)
		Texto: 0 (default) NombreImages is imagename to load, 1 this is a text to show as stimulus.
		agrandar: increase font size, if stimulus is text.
		divisor: proportinal divisor of screen width (int) for font size.
		tamanio: Font size (int).
		colortext: Text color (RGB).
		convert: Convert image to Display type, Default is 0 (False).
		NBackSpatial: 1: Make stimulus for n-Back Spatial experiment.
		NBack: 1: Make stimulus for n-Back experiment.
		FullScreen: 1: Make stimulus for FullScreen experiment.
		Relations: 1: Make stimulus for Relation Experiment.
		DotMixedTask: 1: Make stimulus for Dot Mixed Task Experiment.
		Folder: Image Stimulus Directory.
		colorkey: Transaparency color key index.
		convert: Convert image to Display type, Default is 0 (False).
		Sound: Load sound, 1 sound is named equal dan image or text, if is an string is sound name.
		SoundExtraTime: Extra time after sound, default is 0.
		SoundFolder: Sounds directory. Default is 'Sounds'.
		SoundFileType: Sound file tipe. Default is '.ogg'.
		AddCentralPosition: Makes position for Stimulus Central position in screen. Defaul is 0.
		IgnoreRows=[]
		IgnoreCols=[]
		
		Return an Stimulus."""
		debug('cargarestimulo: NombreImagen:' + NombreImagen)
		isrelation = 0
		esmuestra = 1
		# Class Binding
		if Texto is None:
			Texto = self.GlobalLoadStimulusText
		if divisor is None:
			divisor = self.GlobalLoadStimulusDivisor
		if Relations is None:
			Relations = self.GlobalLoadStimulusRelations
		if Folder is None:
			Folder = self.GlobalLoadStimulusFolder
		if Sound is None:
			Sound = self.GlobalLoadStimulusSound
		if SoundExtraTime is None:
			SoundExtraTime = self.GlobalLoadStimulusSoundExtraTime
		if SoundFolder is None:
			SoundFolder = self.GlobalLoadStimulusSoundFolder
		if SoundFileType is None:
			SoundFileType = self.GlobalLoadStimulusSoundFileType
		if AddCentralPosition is None:
			AddCentralPosition = self.GlobalLoadStimulusAddCentralPosition
		# End Class Binding
		if NBack or FullScreen:
			NroFilasEstimulos = 1; NroColumnasEstimulos = 1
		if NBackSpatial:
			NroFilasEstimulos = 3; NroColumnasEstimulos = 3; NroMuestras = 3; Aplanar = 1
		if Relations:
			NroFilasEstimulos = 3; isrelation = 1
		if (NBack or NBackSpatial) and not divisor:
			divisor=4
		if Relations and not divisor:
			divisor = 12
		if DotMixedTask:
			NroFilasEstimulos = 1; NroColumnasEstimulos = 2; esmuestra = 0
		if not Texto:
			Edir = Folder + os.sep
			imagen=pygame.image.load(Edir+NombreImagen)
			if convert:
				imagen = imagen.convert()
			if colorkey is not None:
				if colorkey is -1:
					colorkey = imagen.get_at((0,0))
				imagen.set_colorkey(colorkey, RLEACCEL)
		else:
			Ancho=len(NombreImagen)
			if not divisor:
				divisor=int(screen.get_width()/Ancho)+agrandar
			if tamanio:
				tamaniotexto=tamanio
			else:
				tamaniotexto=int(screen.get_width()/divisor)+agrandar
			if not colortext:
				colortext=textcolor
			font = pygame.font.Font(letra, tamaniotexto)
			if NombreImagen!="!=":
				if backcolortext:
					imagen = font.render(NombreImagen, 1, (colortext),(backcolortext))
				else:
					imagen = font.render(NombreImagen, 1, (colortext))
			else:
				if backcolortext:
					imagen = font.render("=", 1, (colortext),(backcolortext))
					tacha = font.render("/", 1, (colortext),(backcolortext))
				else:
					imagen = font.render("=", 1, (colortext))
					tacha = font.render("/", 1, (colortext))
				imagen.blit(tacha,tacha.get_rect(center=(imagen.get_width()/2,imagen.get_height()/20*13)))
		if FullScreen:
			newsize = NewFullScreenSize(imagen.get_size())
			FSimagen = pygame.transform.scale(imagen,newsize)
			imagen = FSimagen.copy()
		if not Alias:
			if NombreImagen=="=":
				Alias = "=="
			else:
				Alias = NombreImagen
		estimulo=[Alias,NombreImagen,imagen]
		aplanado=[]
		# Mouse
		MuestraAltura = 0
		Hipotenusa = 0
		# Aspect Ratio Correction
		AspectRatio = (screen.get_width() + 0.0) / (screen.get_height() + 0.0)
		# Use Aspect Ratio Correction only if Aspect Ratio is 5:4
		if AspectRatio<>1.25:
			debug('cargarestimulo: Ignoring ApectRatio Correction.')
			AspectRatio = 1
		for vertical in range(1,NroFilasEstimulos+1):
			if vertical in IgnoreRows:
				continue
			posiciones=[]
			# Normaly you have only a Sample (Muestra) and, if exist, a Relation by trial.
			if esmuestra or isrelation:
				TotalLateral = NroMuestras + 1
				if esmuestra:
					esmuestra = 0
				else:
					isrelation = 0
			else:
				if NroColumnasEstimulos is None:
					TotalLateral=len(self.teclas)+1
				else:
					TotalLateral=NroColumnasEstimulos+1
			for horinzontal in range(1,TotalLateral):
				if horinzontal in IgnoreCols:
					continue
				lateral=(screen.get_width()/(TotalLateral))*horinzontal
				altura=screen.get_height()/(NroFilasEstimulos+1)*vertical
				## print 'Out: ',NombreImagen,vertical,horinzontal
				if self.UseMouse:
					## print 'In: ',NombreImagen,vertical,horinzontal
					if not MuestraAltura:
						## print 'MuestraAltura: ',NombreImagen,vertical,horinzontal
						MuestraLateral = screen.get_width()/2
						MuestraAltura  = altura
					elif (not isrelation) and horinzontal<(TotalLateral-1):
						if not Hipotenusa:
							## print 'Hipotenusa: ',NombreImagen,vertical,horinzontal
							CHorizontal = (MuestraLateral - lateral)
							CVertical   = (altura - MuestraAltura) * AspectRatio
							Hipotenusa  = int(math.hypot(CHorizontal,CVertical))
						elif (TotalLateral/2.0)==horinzontal:
							# This correction is only valid for image at center
							altura = MuestraAltura + Hipotenusa
							## print 'Else: ',NombreImagen,vertical,horinzontal
							## print '******************'
							## print 'NroFilasEstimulos+1: ',(NroFilasEstimulos+1),' vertical: ',vertical
							## print 'MuestraLateral: ', MuestraLateral
							## print 'MuestraAltura : ', MuestraAltura
							## print 'CHorizontal   : ', CHorizontal
							## print 'CVertical     : ', CVertical
							## print 'Hipotenusa    : ', Hipotenusa
							## print 'altura        : ', altura
							## print 'width         : ', screen.get_width()
							## print 'height        : ', screen.get_height()
						else:
							# This is valid for images not at center and not at extrems
							# Not tested yet
							CHorizontal2 = (MuestraLateral - lateral)
							CMayor = int(math.sqrt(math.pow(Hipotenusa,2)-math.pow(CHorizontal2,2)))
							altura = MuestraAltura + CMayor
				posiciones.append(imagen.get_rect(centerx=lateral,centery=altura))
			if Aplanar:
				aplanado=aplanado+posiciones
			else:
				estimulo.append(posiciones)
		if Aplanar:
			estimulo.append(aplanado)
		if AddCentralPosition:
			posiciones=[]
			lateral=screen.get_width()/2
			altura=screen.get_height()/2
			posiciones.append(imagen.get_rect(centerx=lateral,centery=altura))
			estimulo.append(posiciones)
		# Sound
		if Sound:
			if isinstance(Sound,int):
				if Texto:
					SoundName = NombreImagen.lower().strip() + SoundFileType
				else:
					SoundName = string.join(NombreImagen.split(u'.')[:-1],u'.').lower().strip() + SoundFileType
			else:
				if Sound.endswith(u'.wav') or Sound.endswith(u'.ogg') or Sound.endswith(u'.mp3'):
					SoundName = Sound
				else:
					SoundName = Sound + SoundFileType
			sonido = self.cargarsonido(SoundName,SoundFolder)
			try:
				SoundLength = int(sonido.get_length() * 1000)
			except AttributeError:
				SoundLength = None
			estimulo.append([sonido, SoundLength+SoundExtraTime])
		debug('cargarestimulo: estimulo:' + str(estimulo))
		return estimulo

	def cargarimagen(self,NombreImagen,Folder='Imagenes',totalvertical=2,
		verticalpos=1,totallateral=2,lateralpos=1,absoluteverticalpos=None,
		absolutelateralpos=None,colorkey=None,convert=0):
		""" Las imagenes deben estar en el subdirectorio Imagenes
		Images must be in subdirectory Imagenes
		
		Parameters:
		NombreImagen: Image file name to load.
		Folder: Image folder.
		colorkey: Transaparency color key index.
		convert: Convert image to Display type, Default is 0 (False).
		
		Returns a Suface and their centered position."""
		debug('cargarimagen')
		Idir = Folder + os.sep
		if absoluteverticalpos is None:
			altura = (screen.get_height()/totalvertical)*verticalpos
		else:
			altura = absoluteverticalpos
		if absolutelateralpos is None:
			lateral = (screen.get_width()/totallateral)*lateralpos
		else:
			lateral = absolutelateralpos
		if os.access(Idir+NombreImagen,os.F_OK ):
			imagen=pygame.image.load(Idir+NombreImagen)
			if convert:
				imagen = imagen.convert()
			if colorkey is not None:
				if colorkey is -1:
					colorkey = imagen.get_at((0,0))
				imagen.set_colorkey(colorkey, RLEACCEL)
			if absoluteverticalpos is None:
				imagenpos = imagen.get_rect(centerx=lateral,centery=altura)
			else:
				imagenpos = imagen.get_rect(centerx=lateral,y=(altura-imagen.get_height()))
		else:
			imagen = None
			imagenpos = None
		return [imagen,imagenpos]

	def cargarvideo(self,NombreVideo,Folder='Imagenes',totalvertical=2,verticalpos=1,totallateral=2,lateralpos=1,absoluteverticalpos=None,absolutelateralpos=None):
		""" Las videos deben estar en el subdirectorio Imagenes
		Images must be in subdirectory Imagenes
		
		Parameters:
		NombreVideo: Video file name to load.
		
		Returns a Suface and their centered position."""
		debug('cargarvideo')
		Idir = Folder + os.sep
		if absoluteverticalpos is None:
			altura = (screen.get_height()/totalvertical)*verticalpos
		else:
			altura = absoluteverticalpos
		if absolutelateralpos is None:
			lateral = (screen.get_width()/totallateral)*lateralpos
		else:
			lateral = absolutelateralpos
		try:
			imagen=pygame.movie.Movie(Idir+NombreVideo)
		except pygame.error:
			imagen = None
			imagenpos = None
		if not (imagen is None):
			size = xsize,ysize = imagen.get_size()
			lateral = lateral - (xsize/2)
			if absoluteverticalpos is None:
				altura = altura - (ysize/2)
				imagenpos = Rect(lateral,altura,0,0)
				imagenpos.size = size
			else:
				altura = altura - ysize
				imagenpos = Rect(lateral,altura,0,0)
				imagenpos.size = size
		return [imagen,imagenpos]
	
	def CheckVideo(self,Mensaje=[u'¿Puede ver el video? (S/N)','','','',''],NombreVideo='videotest.mpg',Folder='Imagenes'):
		"""Ask user is see some video.
		Use it before use intento.makephrase().
		
		Parameters:
		Mensaje: Message to show. Default is ['¿Puede ver el video? (S/N)'].
		NombreVideo: Video Name, by default is 'videotest.mpg'.
		Folder: Video file folder, by default is 'Imagenes'.
		
		Returns: User aswer: 0 Don't see video. 1 see video.
		"""
		debug('CheckVideo')
		global ShowVideo
		ShowVideo = 0
		cleanscreen()
		pygame.mixer.quit()
		videotest = self.cargarvideo(NombreVideo,Folder)
		if not (videotest[0] is None):
			videotest[0].set_display(screen,videotest[1])
			videotest[0].play(0)
			respuesta = self.texto(Mensaje,CleanScreen=0,AnswerKeys=[K_s,K_n],escsale=1)
			videotest[0].stop()
			videotest[0] = None
			try:
				pygame.mixer.init()
			except pygame.error:
				pass
			if respuesta == K_s:
				ShowVideo = 1
		return ShowVideo

	def cargarsonido(self,nombresonido,Folder=u'Sonidos'):
		""" Los sonidos deben estar en el subdirectorio Sonidos
		Images must be in subdirectory Sonidos.
		
		Sound file must be WAV or OGG file type.
		
		Parameters:
		nombresonido: Sound file name to load.
		Folder: Sound location.
		
		Returns a Pygame Sound object."""
		debug('cargarsonido')
		if Folder:
			nombresonido = Folder+os.sep+nombresonido
		if sys.platform[0:3]=="win":
			nombrearchivosonido = nombresonido.encode('windows-1252')
		else:
			nombrearchivosonido = nombresonido.encode('utf8')
		try:
			sonido=pygame.mixer.Sound(nombrearchivosonido)
			sonido.set_volume(1)
		except pygame.error:
			debug("Error al intentar cargar: "+nombresonido)
			debug("PyGame Error: "+str(pygame.get_error()))
			sonido=0
			if os.access(nombrearchivosonido,os.F_OK ):
				mensaje = ["Fallo de sonido.","Cierre todas las",
				"aplicaciones que usen sonido,","y vuelva a intentar"]
				debug("Fallo General de Sonido")
			else:
				mensaje = ["Archivo de sonido:",nombresonido,"no encontrado.",
				u"Ejecute la aplicación","desde su directorio"]
				debug("Archivo de Sonido no Encontrado: "+nombresonido)
			if SoundRequired:
				self.fallosonido=1
				mensaje = mensaje + ["Imposible continuar sin sonido","",
				"Para salir presione:","La barra espaciadora"]
				self.texto(mensaje)
				raise
			else:
				if not self.fallosonido:
					self.fallosonido=1
					mensaje = mensaje + [u"¿Continuar sin sonido?(S/N)"]
					self.salir(mensaje,K_n,K_s)
		return sonido

	def loadsoundfolder(self,Folder=u'Sonidos'):
		""" Los sonidos deben estar en el subdirectorio Sonidos
		Sounds must be in subdirectory Sonidos.
		
		Sound file must be WAV or OGG file type.
		
		Parameters:
		Folder: Sounds location.
		
		Returns a dictionary of Pygame Sound object
		{'soundfilenamewithoutextension': PygameSoundObject}."""
		debug('loadsoundfolder')
		Sounds = {}
		for soundfileunicode in os.listdir(Folder):
			if sys.platform[0:3]=="win":
				soundfile = soundfileunicode.decode('windows-1252')
			else:
				soundfile = soundfileunicode.decode('utf8')
			Extensions = (".wav",".Wav",".WAv",".WAV",".wAV",".waV"
						 ,".ogg",".Ogg",".OGg",".OGG",".oGG",".ogG")
			if (not soundfile.startswith(".")) and soundfile.endswith(Extensions):
				Sounds[soundfile[:-4].strip().lower()]=self.cargarsonido(soundfile,Folder=Folder)
		return Sounds

	def cargartexto(self,texto,divisor=0,tamanio=0,colortext=0,Left=None,totalvertical=2,verticalpos=1):
		"""Makes a Text as surface.  Return a Surface and their centered position.
		Parameters:
		Texto: Text.
		divisor: proportinal divisor of screen width (int) for font size.
		tamanio: Font size (int).
		colortext: Text color (RGB)."""
		debug('cargartexto')
		altura = (screen.get_height()/totalvertical)*verticalpos
		lateral = screen.get_width()/2
		fullscreenresize = 0
		if not divisor:
			divisor = 6
		if tamanio:
			tamaniotexto=tamanio
		else:
			tamaniotexto=screen.get_width()/divisor
		if not colortext:
			colortext=textcolor
		font = pygame.font.Font(letra, tamaniotexto)
		text = font.render(texto, 1, (colortext))
		if Left is None:
			textpos = text.get_rect(centerx=lateral,centery=altura)
		else:
			textpos = text.get_rect(left=Left,centery=altura)
		return [text,textpos]

class SpriteMovie(pygame.sprite.Sprite):
	def __init__(self, BaseName, Delay=5,Folder='Imagenes',totalvertical=2,
		verticalpos=1,totallateral=2,lateralpos=1,absoluteverticalpos=None,
		absolutelateralpos=None,ScriptAction='Normal',ScriptFlip=[0,0],ScriptRotate=0.0,
		colorkey=None):
		pygame.sprite.Sprite.__init__(self)
		debug('SpriteMovie: Init')
		self.loadImages(Folder,BaseName,ScriptAction,ScriptFlip,ScriptRotate)
		self.frame = 0
		self.image = self.mooImages[self.frame]
		if absoluteverticalpos is None:
			altura = (screen.get_height()/totalvertical)*verticalpos
		else:
			altura = absoluteverticalpos
		if absolutelateralpos is None:
			lateral = (screen.get_width()/totallateral)*lateralpos
		else:
			lateral = absolutelateralpos
		if colorkey is not None:
			self.image = self.image.convert()
			if colorkey is -1:
				colorkey = self.image.get_at((0,0))
			self.image.set_colorkey(colorkey, RLEACCEL)
		# Seting position
		if absoluteverticalpos is None:
			self.rect = self.image.get_rect(centerx=lateral,centery=altura)
		else:
			self.rect = self.image.get_rect(centerx=lateral,y=(altura-self.image.get_height()))
		# increase delay value to slow down animation even more
		self.delay = Delay
		self.pause = 0

	def update(self):
		self.pause += 1
		if self.pause >= self.delay:
			#reset pause and advance animation
			self.pause = 0
			if NextSpritUpdate <= pygame.time.get_ticks():
				self.frame += 1
			if self.frame >= len(self.mooImages):
				self.frame = 0
			self.image = self.mooImages[self.frame]

	def loadImages(self,Folder,BaseName,ScriptAction,ScriptFlip,ScriptRotate):
		self.mooImages = []
		files = os.listdir(Folder+os.sep+BaseName)
		files.sort()
		if ScriptAction == 'Reverse' or ScriptAction == 'FullCircle':
			files.reverse()
		for ucadauno in files:
			cadauno = ucadauno.encode()
			try:
				imgtmp = pygame.image.load(Folder+os.sep+BaseName+os.sep+cadauno)
				imgtmp2 = pygame.transform.flip(imgtmp, ScriptFlip[0], ScriptFlip[1])
				if ScriptRotate:
					imgtmp = pygame.transform.rotate(imgtmp2, ScriptRotate)
				else:
					imgtmp = imgtmp2
				self.mooImages.append(imgtmp)
				if ScriptAction == 'FullCircle' and len(self.mooImages)>1:
					self.mooImages.insert(0,imgtmp)
			except pygame.error:
				pass

class ActionSprite(pygame.sprite.Sprite):
	def __init__(self, Image, Action, Delay=0,totalvertical=2,
		verticalpos=1,totallateral=2,lateralpos=1,absoluteverticalpos=None,
		absolutelateralpos=None,ScriptAction='Normal',colorkey=None):
		debug('ActionSprite: Init')	
		pygame.sprite.Sprite.__init__(self)
		self.image = Image[0]
		if absoluteverticalpos is None:
			altura = (screen.get_height()/totalvertical)*verticalpos
		else:
			altura = absoluteverticalpos
		if absolutelateralpos is None:
			lateral = (screen.get_width()/totallateral)*lateralpos
		else:
			lateral = absolutelateralpos
		if colorkey is not None:
			self.image = self.image.convert()
			if colorkey is -1:
				colorkey = self.image.get_at((0,0))
			self.image.set_colorkey(colorkey, RLEACCEL)
		# Seting position
		# sipe= [[250, 250], [-50,  37], [[[8, 0], 38]], [254,  37]]
		if absoluteverticalpos is None:
			ElLateral = lateral-Action[0][0]/2+Action[1][0]
			LaAltura  = altura-Action[0][1]/2+Action[1][1]
			self.rect = self.image.get_rect(centerx=ElLateral,centery=LaAltura)
		else:
			ElLateral = lateral-Action[0][0]/2+Action[1][0]
			LaAltura  = altura-Action[0][1]+Action[1][1] ##-self.image.get_height()
			self.rect = self.image.get_rect(centerx=ElLateral,y=LaAltura)
		# increase delay value to slow down animation even more
		self.StartPos = self.rect
		self.delay = Delay
		self.pause = 0
		self.step = 0
		self.stepcount = 0
		self.trajectory = Action[2]

	def update(self):
		self.pause += 1
		if self.pause >= self.delay:
			if NextSpritUpdate <= pygame.time.get_ticks():
				if self.step<len(self.trajectory):
					self.rect = self.rect.move((self.trajectory[self.step][0]))
					self.stepcount += 1
					if self.stepcount >= self.trajectory[self.step][1]:
						self.step += 1
						self.stepcount = 0
				else:
					self.rect = self.StartPos
					self.stepcount = 0
					self.step = 0

def NewFullScreenSize(ImageSize):
	"""Returns proportional size for an full screen presentation of one image
	Parameters:
	ImageSize:  Actual image size"""
	debug('NewFullScreenSize')
	Ix, Iy = ImageSize
	Ux, Uy = usersize
	Nx = Ux
	Ny = Iy * Ux / Ix
	if Ny > Uy:
		Ny = Uy		
		Nx = Ix * Uy / Iy
	NewSize = (Nx, Ny)
	return NewSize


def cleanscreen():
	"""Clear the screen.  No parameters."""
	debug('cleanscreen')
	screen.fill(background)
	pygame.display.flip()
	screen.fill(background)


def permutar(seq):
	"""Permutate a sequence and return a list of the permutations
	Parameters:
	seq: is a list to permutate
	
	A simple recursive permutation function
	the number of permutations of a sequence of n unique items is given by n!
	more details at http://mathworld.wolfram.com/Permutation.html
	tested with Python24 vegaseat 16feb2006"""
	debug('permutar')
	if not seq:
		return [seq]
	else:
		temp = []
		for k in range(len(seq)):
			part = seq[:k] + seq[k+1:]
			for m in permutar(part):
				temp.append(seq[k:k+1] + m)
		return temp


def combinar(elementos,tomar=0):
	"""Returns a limited number of elements permuted
	Parameters:
	elementos: a list to permutate
	tomar: numbers of items to return for each permutation"""
	debug('combinar')
	if tomar==0 or tomar>len(elementos):
		tomar=len(elementos)
	permutados=permutar(elementos)
	tomados=[]
	for cadauno in permutados:
		if not (cadauno[0:tomar] in tomados) and sinrepeticiones(cadauno[0:tomar]):
			tomados.append(cadauno[0:tomar])
	return tomados

def sinrepeticiones(candidato):
	"""Check if an Permutation have repeated elements.
	Necesary because Relations stimulus can have diferents stimulus for the same
	elements.
	
	Parameters:
	candidato: Permutation to check.
	
	Returns: 0 (Exists repeated elements) or 1 (Not exists)"""
	debug('sinrepeticiones')
	candidate=[]
	for eachstimulus in candidato:
		candidate.append(eachstimulus[0])
	SinRepetir = 1
	for eachstimulus in candidate:
		if candidate.count(eachstimulus)>1:
			SinRepetir = 0
	return SinRepetir

def tomarparametros():
	"""Takes parameters from command line.  No method parameters."""
	debug('tomarparametros')
	global usersize,shortflag,prueba,grupo,configflag,blackback,expertflag,eegsyncmintime
	global eegsync,eegsyncport,eegbaudrate,MaxHResolution,debugging,excludelist,randomresponse
	global quickrandomresponse, codigosujeto, edadsujeto, generosujeto
	global Condition, SoundRecorder, RESEARCHER
	excludelist = []
	randomresponse = 0
	quickrandomresponse = 0
	debugging = 0
	MaxHResolution = 0
	configflag = 0
	expertflag = 0
	blackback = 0
	shortflag = 0
	if len(sys.argv)>1:
		opts, args = getopt.getopt(sys.argv[1:],'a:bC:cd:DE:eG:g:hln:p:qr:RsS:t:xX:', ['blackback',
		'condition=','config','device=','debug','edad=','eeg','exclude=','expert','genero=',
		'grupo=','help','listen','name=','prueba=',	'quick','random','resolucion=','short',
		'speed','time='])
		for o, a in opts:
			if o in ("-a", "--researcher"):
				RESEARCHER = a
			if o in ("-b", "--blackback"):
				blackback = 1
			if o in ("-C", "--condition"):
				Condition = a
			if o in ("-c", "--config"):
				configflag = 1
			if o in ("-S", "--speed"):
				try:
					eegbaudrate = int(a)
				except ValueError:
					pass
			if o in ("-d", "--device"):
				try:
					eegsyncport = int(a)
				except ValueError:
					if re.compile("^[Cc][Oo][Mm]").match(a, 0):
						eegsyncport = a.upper()
					else:
						eegsyncport = a
			if o in ("-t", "--time"):
				try:
					eegsyncmintime = int(a)
				except ValueError:
					pass
			if o in ("-D", "--debug"):
				debugging = 1
			if o in ("-E", "--edad"):
				edadsujeto = a
			if o in ("-e", "--eeg"):
				if SerialLoaded:
					eegsync=1
			if o in ("-G", "--genero"):
				if a.upper() in ['F','M']:
					generosujeto = a.upper()
			if o in ("-g", "--grupo"):
				grupo = a
			if o in ("-h", "--help"):
				usage()
				sys.exit()
			if o in ("-l", "--listen"):
				SoundRecorder = 1
			if o in ("-n", "--name"):
				codigosujeto = a
			if o in ("-p", "--prueba"):
				prueba = a
			if o in ("-q", "--quick"):
				quickrandomresponse = 1
			if o in ("-R", "--random"):
				randomresponse = 1
			if o in ("-r", "--resolucion"):
				resolucion=a.lower().split('x')
				usersize = width, height =  int(resolucion[0]),int(resolucion[1])
			if o in ("-s", "--short"):
				shortflag = 1
			if o in ("-x", "--expert"):
				expertflag=1
			if o in ("-X", "--exclude"):
				excludelist = a.split(',')
		if eegsync:
			resultado = checkport(eegsyncport,eegbaudrate,eegsyncmintime)
			if not resultado[0]:
				eegsync = 0
				debug("Fallo el puerto Serie "+str(eegsyncport)+". Mensaje de Error: "+resultado[1])
	if not debugging:
		debugging = 1
		debug('*** Running Experiment - Stop Debug: '+time.strftime('%x %X UTC', time.gmtime(time.time())))
		debugging = 0

def usage():
	"""Display to standard output a message about usage of comand line parameters."""
	debug('usage')
	print """
Parametros de linea de comando:

-a, --researcher= Especifica el nombre del investigador. 
-b, --blackback  Deja la pantalla negra y letras blancas, cuando esta permitido.
-C, --condition= Especifica la condición de muestra, cuando esta disponible.
-c, --config     Muestra la ventana gráfica de configuración
-D, --debug      Guarda datos de seguimiento de errores, no usar en toma de datos.
-d, --device=    Especifica el dispositivo de sincronización EEG (0 por omisión).
-E, --edad=      Especifica la edad del sujeto.
-e, --eeg        Activa la sincronización a puerto serie para EEG.
-G, --genero=    Especifica el Sexo del sujeto.
-g, --grupo=     Especifica el grupo de muestra, cuando esta disponible.
-h, --help	     Muestra esta ayuda y termina
-i, --ignore     StarExperiment: Ignora otros parámetros, solo toma los actuales de la línea de comandos
-l, --listen     Grabar sonido, se necesita configuración especial.
-n, --name=      Especifica el código del sujeto, solo usado para pruebas.
-p, --prueba=    Especifica el nombre de la prueba a tomar, cuando esta disponible.
-q, --quick      Respuestas rápidas aleatorias (para pruebas de calidad).
-R, --random     Respuestas aleatorias (para pruebas de calidad).
-r, --resolucion=  P.E: -r800x600 fija la resolución de pantalla en 800x600
-s, --short	     Pone todos los valores de control en -1, excepto PresentarTodos
-S, --speed=     Fija la velocidad de sincronización de EEG (9600 baudios por omisión)
-t, --time=      Fija el tiempo minimo de emisión de señal de EEG.
-x, --expert     Presenta la configuración gráfica completa.
-X, --exclude=   Excluye las secciones especificadas en la ejecución del experimento.
                 Solo para pruebas de calidad.
"""

def checkport(port,baudrate,txtime=None):
	"""Check if given serial port can be used.
	
	Parameters:
	
	port: serial port.
	baudrate: bit rate to test.
	
	Returns a list [int, string]
	int: 0 fail, 1 susseccful
	string: Error message."""
	debug('checkport')
	if txtime is None:
		txtime = eegsyncmintime
	# Abrir puerto Serial - EEG Sync
	if SerialLoaded:
		OK=1
		puertoserial=0
		mensaje="Algo Mal"
		try:
			puertoserial = serial.Serial(port,baudrate)
		except serial.serialutil.SerialException:
			OK=0
			mensaje="Puerto Mal"
		except ValueError:
			OK=0
			mensaje="Veloc. Mal"
		if puertoserial:
			# EEG Sync
			puertoserialfinish = pygame.time.get_ticks() + txtime
			while OK and puertoserialfinish>pygame.time.get_ticks():
				try:
					puertoserial.flushOutput()
				except serial.serialutil.SerialException:
					OK=0
				try:	
					puertoserial.write(hex(0))
				except serial.serialutil.SerialException:
					OK=0
			# Cerrar puerto Serial - EEG Sync
			try:
				puertoserial.flushOutput()
			except serial.serialutil.SerialException:
				OK=0
			try:	
				puertoserial.close()
			except serial.serialutil.SerialException:
				OK=0
		if OK:
			mensaje="Puerto OK"
	else:
		OK=0
		mensaje="No Modulo Serial"
	return [OK,mensaje]

def DisplayFix(color=None,radius=2):
	"""Make a surface dot.
	
	Parameters:
	color: Dot Color, Default is textcolor
	radius: Dot radius, Default is 2.
	
	Returns: Surface"""
	debug('DisplayFix')
	if color is None:
		color = textcolor
	surf = pygame.Surface(usersize)
	surf.fill(background)
	CX = screen.get_width()/2
	CY = screen.get_height()/2
	pygame.draw.circle(surf,(color),(CX,CY),radius,0)
	return surf

class ConfigFrame(wx.Frame):
	"""Configuration Windows Class.  No parameters."""
	def __init__(self):
		global codigosujeto
		if sys.platform[0:3]=="win":
			if expertflag:
				myFsize = (315, 460)
			else:
				myFsize = (315, 195)
			myTsize = (65,20)
			myTCSsize = (200,20)
		else:
			if expertflag:
				myFsize = (310, 440)
			else:
				myFsize = (310, 170)
			myTsize = (78,26)
			myTCSsize = (200,26)
		BaudRates = ['300', '600', '1200', '2400', '4800', '9600', '14400', '19200', '38400', '57600', '115200']
		SerialPorts = ['0', '1', '2', '3']
		wx.Frame.__init__(self, None, -1, u"Configuración del Experimento", size=myFsize,
		style=wx.DEFAULT_DIALOG_STYLE)
		if sys.platform[0:3]=="win":
			self.Icon = wx.Icon('Icons'+os.sep+'configuration_edit.ico',wx.BITMAP_TYPE_ICO)
		else:
			self.Icon = wx.Icon('Icons'+os.sep+'configuration_edit.png',wx.BITMAP_TYPE_PNG)
		self.SetIcon(self.Icon)
		panel = wx.Panel(self, -1)
		self.continuar=0
		# Nombre del Investigador - Researcher Name
		wx.StaticText(panel, -1, u"Investigador:", (5, 10))
		self.Investigador = wx.TextCtrl(panel, -1, RESEARCHER, size=myTCSsize, pos=(100, 4))
		# Codigo Sujeto - Subject Code
		wx.StaticText(panel, -1, u"Código Sujeto:", (5, 40))
		self.CodigoSujeto = wx.TextCtrl(panel, -1, codigosujeto, size=myTCSsize, pos=(100, 34))
		# Edad - Age
		wx.StaticText(panel, -1, u"Edad:", (5, 70))
		self.EdadSujeto = wx.TextCtrl(panel, -1, edadsujeto, size=myTsize, pos=(100, 64))
		# Genero - Sex
		wx.StaticText(panel, -1, u"Sexo:", (188, 70))
		self.GeneroSujeto = wx.ComboBox(panel, -1, generosujeto, (228, 64), (72,30),
		["F","M"], wx.CB_DROPDOWN | wx.CB_READONLY)
		# Resolucion de pantalla - Screen Resolution
		myCBSize=(200, 30)
		STRusersize = str(usersize)[1:-1].replace(', ','x')
		STRresols = []
		for cadauno in pygame.display.list_modes():
			STRresols.append(str(cadauno)[1:-1].replace(', ','x'))
		DefaultValue = ""
		if STRusersize in STRresols:
			DefaultValue = STRusersize
		wx.StaticText(panel, -1, u"Resolución:", (5, 100))
		self.Resol = wx.ComboBox(panel, -1, DefaultValue, (100, 94), myCBSize,
		STRresols, wx.CB_DROPDOWN | wx.CB_READONLY)
		if expertflag:
			# Seleccionar Experimento - Select Experiment
			DefaultValue = ""
			if prueba in Tasks:
				DefaultValue = prueba
			wx.StaticText(panel, -1, u"Experimento:", (5, 130))
			self.Task = wx.ComboBox(panel, -1, DefaultValue, (100, 124), myCBSize,
			Tasks, wx.CB_DROPDOWN | wx.CB_READONLY)
			# Seleccionar Grupo - Select Group
			DefaultValue = ""
			if grupo in Groups:
				DefaultValue = grupo
			wx.StaticText(panel, -1, u"Grupo:", (5, 160))
			self.Group = wx.ComboBox(panel, -1, DefaultValue, (100, 154), myCBSize,
			Groups, wx.CB_DROPDOWN | wx.CB_READONLY)
			# Seleccionar Condición - Select Condition
			DefaultValue = ""
			if Condition in Conditions:
				DefaultValue = grupo
			wx.StaticText(panel, -1, u"Condición:", (5, 190))
			self.Condicion = wx.ComboBox(panel, -1, DefaultValue, (100, 184), myCBSize,
			Conditions, wx.CB_DROPDOWN | wx.CB_READONLY)
			# Configuración EEG - EEG Configuration
			wx.StaticText(panel, -1, u"Configuración de Sincronia EEG:", pos=(5, 220))
			# EEG Check Box
			self.EEG = wx.CheckBox(panel, -1, u"Activar", (225, 218), (200, 20))
			self.EEG.SetValue(eegsync)
			# EGG Minimal Time Text Box
			wx.StaticText(panel, -1, u"Tiempo de Transmisión (ms):", (5, 250))
			self.TxTime = wx.SpinCtrl(panel, -1, "", (200, 244), (myTsize))
			self.TxTime.SetRange(1,100)
			self.TxTime.SetValue(eegsyncmintime)
			# Combo Drop List
			wx.StaticText(panel, -1, u"Puerto:", (5, 280))
			self.Port = wx.ComboBox(panel, -1, str(eegsyncport), (90, 274), (100,30),
			SerialPorts, wx.CB_DROPDOWN)
			# Combo Drop List
			wx.StaticText(panel, -1, u"Velocidad:", (5, 310))
			self.Speed = wx.ComboBox(panel, -1, str(eegbaudrate), (90, 304), (100,30),
			BaudRates, wx.CB_DROPDOWN)
			# Boton prueba puerto
			self.CheckPort = wx.Button(panel, -1, u"Probar Puerto", pos=(200, 271))
			self.Bind(wx.EVT_BUTTON, self.CheckPort_OnClick, self.CheckPort)
			# Texto prueba
			self.TestText = wx.TextCtrl(panel, -1, u"Sin Probar", size=myTsize,
			pos=(210, 304),style=wx.TE_READONLY)
			# Exclude List
			DefaultValue = ""
			wx.StaticText(panel, -1, u"Excluir Pasos:", (5, 340))
			self.ExcludeList = wx.CheckListBox(panel, -1, (100, 334), myCBSize,
			ExcludeableList, wx.LB_SINGLE)
			for item in excludelist:
				Pos = self.ExcludeList.FindString(item)
				if Pos>=0:
					self.ExcludeList.Check(Pos, 1)
			# Other Parameters
			DefaultValue = ""
			self.OtherOptions = ['blackback','debugging','SoundRecorder','quickrandomresponse','randomresponse','shortflag']
			wx.StaticText(panel, -1, u"Más Opciones:", (5, 370))
			self.MoreOptions = wx.CheckListBox(panel, -1, (100, 364), myCBSize,
			self.OtherOptions, wx.LB_SINGLE)
			for OOption in self.OtherOptions:
				if eval(OOption):
					self.MoreOptions.Check(self.MoreOptions.FindString(OOption), 1)
		if expertflag:
			myBposVert = 400
		else:
			myBposVert = 130
		# Botones Inferiores
		self.Save = wx.Button(panel, -1, u"Guardar", pos=(10, myBposVert))
		self.Bind(wx.EVT_BUTTON, self.Save_OnClick, self.Save)
		self.OK = wx.Button(panel, -1, u"Iniciar", pos=(109, myBposVert))
		self.Bind(wx.EVT_BUTTON, self.OK_OnClick, self.OK)
		self.OK.SetDefault()
		self.Cancel = wx.Button(panel, -1, u"Salir", pos=(208, myBposVert))
		self.Bind(wx.EVT_BUTTON, self.Cancel_OnClick, self.Cancel)
		self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
		if RESEARCHER:
			self.CodigoSujeto.SetFocus()
		else:
			self.Investigador.SetFocus()
	
	def Save_OnClick(self, event):
		"""Configuration Windows Class Method."""
		self.consolidar()
		diskconfig('write')
	
	def CheckPort_OnClick(self, event):
		"""Configuration Windows Class Method."""
		self.RunCheckPort(int(self.Port.GetValue()),int(self.Speed.GetValue()),int(self.TxTime.GetValue()))

	def OK_OnClick(self, event):
		"""Configuration Windows Class Method."""
		if expertflag:
			if (not SerialLoaded) and self.EEG.GetValue():
				dlg=wx.MessageDialog(None, "El modulo Serial no esta cargado.\nNo se puede usar el puerto Serie.",
				caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
				dlg.SetIcon(self.Icon)
				result = dlg.ShowModal()
				dlg.Destroy()
				self.EEG.SetValue(0)
				selfTestTextGetValue = "No Modulo Serial"
				self.TestText.SetValue(selfTestTextGetValue)
			else:
				self.RunCheckPort(int(self.Port.GetValue()),int(self.Speed.GetValue()),int(self.TxTime.GetValue()))
				selfTestTextGetValue = self.TestText.GetValue()
		else:
			selfTestTextGetValue = "Puerto OK"
		if selfTestTextGetValue!="Puerto OK" and self.EEG.GetValue():
			dlg=wx.MessageDialog(None, "El puerto no esta bien configurado.",
			caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
			dlg.SetIcon(self.Icon)
			result = dlg.ShowModal()
			dlg.Destroy()
		elif self.CodigoSujeto.GetValue()=='':
			dlg=wx.MessageDialog(None, u"Debe ingresar un Código de Sujeto.",
			caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
			dlg.SetIcon(self.Icon)
			result = dlg.ShowModal()
			dlg.Destroy()
		elif self.EdadSujeto.GetValue()=='' or not(self.EdadSujeto.GetValue() in EdadesValidas):
			dlg=wx.MessageDialog(None, u"Debe ingresar la Edad del Sujeto (Números).",
			caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
			dlg.SetIcon(self.Icon)
			result = dlg.ShowModal()
			dlg.Destroy()
		elif self.GeneroSujeto.GetValue()=='':
			dlg=wx.MessageDialog(None, u"Debe ingresar el Sexo del Sujeto.",
			caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
			dlg.SetIcon(self.Icon)
			result = dlg.ShowModal()
			dlg.Destroy()
		else:
			self.continuar=1
			self.consolidarERROR=0
			self.consolidar()
			if not self.consolidarERROR:
				self.Close(True)

	def Cancel_OnClick(self, event):
		"""Configuration Windows Class Method."""
		self.Close(True)
		sys.exit()
	
	def OnCloseWindow(self, event):
		"""Configuration Windows Class Method."""
		self.Destroy()
		if not self.continuar:
			sys.exit()

	def RunCheckPort(self, port, baudrate, txtime):
		"""Configuration Windows Class Method."""
		# Abrir puerto Serial - EEG Sync
		self.TestText.SetValue(checkport(port, baudrate, txtime)[1])

	def consolidar(self):
		"""Configuration Windows Class Method."""
		global codigosujeto, edadsujeto, generosujeto, usersize, RESEARCHER
		# Subject Code
		try:
			codigosujeto=string.join(re.split(' *',self.CodigoSujeto.GetValue().strip()),'_').encode()
		except:
			self.consolidarERROR=1
			self.EncodingErrorMessage(u"El código de sujeto no puede contener:\nCarácteres del Castellano (á, é, í, ó, ú, ñ).")
		# Researcher Name
		try:
			RESEARCHER=string.join(re.split(' *',self.Investigador.GetValue().strip()),'_').encode()
		except:
			self.consolidarERROR=1
			self.EncodingErrorMessage(u"El nombre del investigador no puede contener:\nCarácteres del Castellano (á, é, í, ó, ú, ñ).")
		edadsujeto = self.EdadSujeto.GetValue()
		generosujeto = self.GeneroSujeto.GetValue()
		resolucion=self.Resol.GetValue().lower().split('x')
		usersize = width, height =  int(resolucion[0]),int(resolucion[1])
		if expertflag:
			global prueba, grupo, Condition, eegsync, eegsyncport, eegsyncmintime
			prueba = self.Task.GetValue()
			grupo = self.Group.GetValue()
			Condition = self.Condicion.GetValue()
			eegsync = self.EEG.GetValue()
			eegsyncport=int(self.Port.GetValue())
			eegbaudrate=int(self.Speed.GetValue())
			eegsyncmintime=int(self.TxTime.GetValue())
			global excludelist
			excludelist = []
			for item in ExcludeableList:
				if self.ExcludeList.IsChecked(self.ExcludeList.FindString(item)):
					excludelist.append(item)
			for OOption in self.OtherOptions:
				if self.MoreOptions.IsChecked(self.MoreOptions.FindString(OOption)):
					exec('global ' + OOption + ' ; ' + OOption + ' = 1')
				else:
					exec('global ' + OOption + ' ; ' + OOption + ' = 0')

	def EncodingErrorMessage(self,DialogMessage):
		dlg=wx.MessageDialog(None, DialogMessage,
		caption=u"Error de Configuración",style=wx.OK|wx.ICON_ERROR,pos=wx.DefaultPosition)
		dlg.SetIcon(self.Icon)
		result = dlg.ShowModal()
		dlg.Destroy()

	
def configure():
	"""Show the Configuration Windows. No parameters."""
	global Icon
	debug('Start Grafical Config')
	app = wx.PySimpleApp()
	frame = ConfigFrame()
	frame.Show(True)
	app.MainLoop()
	debug('End Grafical Config')
	
class UTF8Recoder:
    """
    Iterator that reads an encoded stream and reencodes the input to UTF-8
    """
    def __init__(self, f, encoding):
        self.reader = codecs.getreader(encoding)(f)

    def __iter__(self):
        return self

    def next(self):
        return self.reader.next().encode("utf-8")

class UnicodeReader:
    """
    A CSV reader which will iterate over lines in the CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        f = UTF8Recoder(f, encoding)
        self.reader = csv.reader(f, dialect=dialect, **kwds)

    def next(self):
        row = self.reader.next()
        return [unicode(s, "utf-8") for s in row]

    def __iter__(self):
        return self

class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

def startsoundrecorder():
	"""Start Recording"""
	global soundrecorderpid, soundrecordernumberfile, SoundFileName
	debug('Start Recording: '+NombreArchivoSonido+'_'+str(soundrecordernumberfile).zfill(2)+TipoDeArchivoSonido)
	if (not soundrecorderpid) and SoundRecorder:
		if (soundrecordernumberfile==1) and (not os.path.exists(SoundRecordFolder)):
			os.makedirs(SoundRecordFolder)
		SoundFileName=NombreArchivoSonido+'_'+str(soundrecordernumberfile).zfill(5)
		FullSoundFileName = SoundRecordFolder+os.sep+SoundFileName+TipoDeArchivoSonido
		if sys.platform[0:3]=="win":
			if win32TerminateProcessLoaded:
				soundrecorderpid = subprocess.Popen(['SoundCapture\SoundCapture.exe','/wav','/mono','/m','240',FullSoundFileName],creationflags=CREATE_NEW_PROCESS_GROUP)
		else:
			soundrecorderpid = subprocess.Popen(['arecord','-f','S16_LE','-c1','-r44100', FullSoundFileName])
		soundrecordernumberfile += 1
	else:
		debug('Start Recording: Ya se esta grabando un archivo de sonido')

def stopsoundrecorder():
	"""Stop Recording"""
	debug('Stop Recording: '+NombreArchivoSonido)
	global soundrecorderpid
	if soundrecorderpid and SoundRecorder:
		if sys.platform[0:3]=="win":
			if win32TerminateProcessLoaded:
				# Terminate the process using pywin32
				GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,soundrecorderpid.pid)
		else:
			os.kill(soundrecorderpid.pid,15)
		soundrecorderpid = 0
	else:
		debug('Stop Recording: No se esta grabando un archivo de sonido')
	
def restartsoundrecorder():
	debug('Restart Recording')
	if SoundRecorder:
		stopsoundrecorder()
		startsoundrecorder()

def loadcommand(filename,sheetname,columnname):
	global debugging
	debug('Load Command')
	doc = ooolib.Calc()
	doc.load(filename)
	sheetindex = None
	for sheet in range(len(doc.sheets)):
		doc.set_sheet_index(sheet)
		if doc.get_sheet_name()==sheetname:
			sheetindex = sheet
			break
	if not(sheetindex is None):
		cols, rows  = doc.get_sheet_dimensions()
		CFC = []
		commands = []
		for row in range(1,rows+1):
			columns = []
			for col in range(1,cols+1):
				if doc.get_cell_value(col,row) is None:
					tipocelda, valorcelda = ('string',u'')
				else:
					tipocelda, valorcelda = doc.get_cell_value(col,row)
				valorcelda = valorcelda.replace('&amp;', '&')
				valorcelda = valorcelda.replace('&apos;', "'")
				valorcelda = valorcelda.replace('&quot;', '"')
				valorcelda = valorcelda.replace('&lt;', '<')
				valorcelda = valorcelda.replace('&gt;', '>')
				valorcelda = valorcelda.replace('<text:tab-stop/>', '\t')
				valorcelda = valorcelda.replace('<text:line-break/>', '\n')
				if not isinstance(valorcelda,basestring):
					valorcelda = str(valorcelda)
				columns.append(valorcelda)
			CFC.append(columns)
		rownumber = 0
		for row in CFC:
			colnumber = 0
			for item in row:
				if item==columnname:
					CommandFileCol = copy.copy(colnumber)
					CommandFileRow = copy.copy(rownumber)
					break
				colnumber += 1
			if item==u'SoundFile':
				break
			rownumber += 1
		for row in CFC[CommandFileRow+1:]:
			if row[CommandFileCol].strip():
				commands.append(row[CommandFileCol])
	else:
		debugging = 1
		debug('*** Error: Sheet not Found: '+sheetname)
		sys.exit()
	return commands
